Hello community, here is the log from the commit of package akonadi-server for openSUSE:Factory checked in at 2016-06-20 11:05:54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/akonadi-server (Old) and /work/SRC/openSUSE:Factory/.akonadi-server.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "akonadi-server" Changes: -------- --- /work/SRC/openSUSE:Factory/akonadi-server/akonadi-server.changes 2016-05-31 12:22:33.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.akonadi-server.new/akonadi-server.changes 2016-06-20 11:05:56.000000000 +0200 @@ -1,0 +2,13 @@ +Tue Jun 14 21:24:55 UTC 2016 - [email protected] + +- Use shared-mime-info macros (boo#979301) + +------------------------------------------------------------------- +Fri Jun 10 17:45:29 UTC 2016 - [email protected] + +- Update to KDE Applications 16.04.2 + * KDE Applications 16.04.2 + * https://www.kde.org/announcements/announce-applications-16.04.2.php + + +------------------------------------------------------------------- Old: ---- akonadi-16.04.1.tar.xz New: ---- akonadi-16.04.2.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ akonadi-server.spec ++++++ --- /var/tmp/diff_new_pack.69CNRx/_old 2016-06-20 11:05:57.000000000 +0200 +++ /var/tmp/diff_new_pack.69CNRx/_new 2016-06-20 11:05:57.000000000 +0200 @@ -17,7 +17,7 @@ Name: akonadi-server -Version: 16.04.1 +Version: 16.04.2 Release: 0 %define rname akonadi Summary: PIM Storage Service @@ -130,11 +130,11 @@ %post /sbin/ldconfig -%{_kf5_bindir}/update-mime-database %{_kf5_sharedir}/mime &> /dev/null || : +%mime_database_post %postun /sbin/ldconfig -%{_kf5_bindir}/update-mime-database %{_kf5_sharedir}/mime &> /dev/null || : +%mime_database_postun %post -n libKF5AkonadiWidgets5 -p /sbin/ldconfig %postun -n libKF5AkonadiWidgets5 -p /sbin/ldconfig ++++++ akonadi-16.04.1.tar.xz -> akonadi-16.04.2.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/CMakeLists.txt new/akonadi-16.04.2/CMakeLists.txt --- old/akonadi-16.04.1/CMakeLists.txt 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/CMakeLists.txt 2016-05-31 11:33:56.000000000 +0200 @@ -21,7 +21,7 @@ include(AkonadiMacros) set(QT_REQUIRED_VERSION "5.2.0") -set(AKONADI_VERSION "5.2.1") +set(AKONADI_VERSION "5.2.2") set(KF5_VERSION "5.16.0") ecm_setup_version(${AKONADI_VERSION} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/core/collectionsync.cpp new/akonadi-16.04.2/src/core/collectionsync.cpp --- old/akonadi-16.04.1/src/core/collectionsync.cpp 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/core/collectionsync.cpp 2016-05-31 11:33:56.000000000 +0200 @@ -644,8 +644,20 @@ //Prevent double result emission Q_ASSERT(!resultEmitted); if (!resultEmitted) { - resultEmitted = true; - q->emitResult(); + if (q->hasSubjobs()) { + // If there are subjobs, pick one, wait for it to finish, then + // try again. This way we make sure we don't emit result() signal + // while there is still a Transaction job running + KJob *subjob = q->subjobs().at(0); + connect(subjob, &KJob::result, + q, [this](KJob*) { + emitResult(); + }, + Qt::QueuedConnection); + } else { + resultEmitted = true; + q->emitResult(); + } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/core/jobs/collectioncopyjob.cpp new/akonadi-16.04.2/src/core/jobs/collectioncopyjob.cpp --- old/akonadi-16.04.1/src/core/jobs/collectioncopyjob.cpp 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/core/jobs/collectioncopyjob.cpp 2016-05-31 11:33:56.000000000 +0200 @@ -74,7 +74,7 @@ bool CollectionCopyJob::doHandleResponse(qint64 tag, const Protocol::Command &response) { - if (!response.isResponse() || response.type() != Protocol::Command::CreateCollection) { + if (!response.isResponse() || response.type() != Protocol::Command::CopyCollection) { return Job::doHandleResponse(tag, response); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/core/jobs/job.cpp new/akonadi-16.04.2/src/core/jobs/job.cpp --- old/akonadi-16.04.1/src/core/jobs/job.cpp 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/core/jobs/job.cpp 2016-05-31 11:33:56.000000000 +0200 @@ -62,7 +62,14 @@ } } + if (mReadingFinished) { + qCWarning(AKONADICORE_LOG) << "Received response for a job that does not expect any more data, ignoring"; + Q_ASSERT(!mReadingFinished); + return; + } + if (q->doHandleResponse(tag, response)) { + mReadingFinished = true; QTimer::singleShot(0, q, SLOT(delayedEmitResult())); } } @@ -149,8 +156,13 @@ void JobPrivate::delayedEmitResult() { Q_Q(Job); - aboutToFinish(); - q->emitResult(); + if (q->hasSubjobs()) { + // We still have subjobs, wait for them to finish + mFinishPending = true; + } else { + aboutToFinish(); + q->emitResult(); + } } void JobPrivate::startQueued() @@ -190,6 +202,9 @@ Job *job = qobject_cast<Akonadi::Job *>(q->subjobs().at(0)); Q_ASSERT(job); job->d_ptr->startQueued(); + } else if (mFinishPending && !q->hasSubjobs()) { + // The last subjob we've been waiting for has finished, emitResult() finally + QTimer::singleShot(0, q, SLOT(delayedEmitResult())); } } @@ -343,17 +358,10 @@ bool Job::doHandleResponse(qint64 tag, const Protocol::Command &command) { - // FIXME: We cannot set an error here due to how CollectionSync works: CS - // can sometimes schedule TransactionSequences and emitResult in a way that - // the Session dispatches next job in queue without TransactionSequence's - // TransactionCommitJob finishing: the we get the response for TCJ out-of-order - // and it's received by the currently running job instead of the TCJ. qCDebug(AKONADICORE_LOG) << this << "Unhandled response: " << tag << command.debugString(); - /* setError(Unknown); setErrorText(i18n("Unexpected response")); emitResult(); - */ return true; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/core/jobs/job_p.h new/akonadi-16.04.2/src/core/jobs/job_p.h --- old/akonadi-16.04.1/src/core/jobs/job_p.h 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/core/jobs/job_p.h 2016-05-31 11:33:56.000000000 +0200 @@ -42,7 +42,9 @@ , mCurrentSubJob(0) , mSession(0) , mWriteFinished(false) + , mReadingFinished(false) , mStarted(false) + , mFinishPending(false) { } @@ -126,7 +128,9 @@ qint64 mTag; Session *mSession; bool mWriteFinished; + bool mReadingFinished; bool mStarted; + bool mFinishPending; }; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/core/jobs/tagmodifyjob.cpp new/akonadi-16.04.2/src/core/jobs/tagmodifyjob.cpp --- old/akonadi-16.04.1/src/core/jobs/tagmodifyjob.cpp 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/core/jobs/tagmodifyjob.cpp 2016-05-31 11:33:56.000000000 +0200 @@ -69,15 +69,17 @@ { Q_D(TagModifyJob); - if (response.isResponse() && (response.type() == Protocol::Command::DeleteTag - || response.type() == Protocol::Command::ModifyTag)) { - ChangeMediator::invalidateTag(d->mTag); - return true; - } - - // We ignore the result for now - if (response.isResponse() && response.type() == Protocol::Command::FetchTags) { - return false; + if (response.isResponse()) { + if (response.type() == Protocol::Command::FetchTags) { + // Tag was modified, we ignore the response for now + return false; + } else if (response.type() == Protocol::Command::DeleteTag) { + // The tag was deleted/merged + return false; + } else if (response.type() == Protocol::Command::ModifyTag) { + // Done. + return true; + } } return Job::doHandleResponse(tag, response); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/core/models/tagmodel.cpp new/akonadi-16.04.2/src/core/models/tagmodel.cpp --- old/akonadi-16.04.1/src/core/models/tagmodel.cpp 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/core/models/tagmodel.cpp 2016-05-31 11:33:56.000000000 +0200 @@ -88,6 +88,9 @@ { Q_D(const TagModel); + if (!index.isValid()) { + return QVariant(); + } const Tag tag = d->tagForIndex(index); if (!tag.isValid()) { return QVariant(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/core/pluginloader.cpp new/akonadi-16.04.2/src/core/pluginloader.cpp --- old/akonadi-16.04.1/src/core/pluginloader.cpp 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/core/pluginloader.cpp 2016-05-31 11:33:56.000000000 +0200 @@ -103,8 +103,8 @@ QObject *object = loader->instance(); if (!object) { - qCWarning(AKONADICORE_LOG) << "unable to load plugin for plugin name \"" << name << "\"." << endl; - qCWarning(AKONADICORE_LOG) << "Error was:\"" << loader->errorString() << "\"." << endl; + qCWarning(AKONADICORE_LOG) << "unable to load plugin" << info.library << "for plugin name" << name << "."; + qCWarning(AKONADICORE_LOG) << "Error was:\"" << loader->errorString() << "\"."; return 0; } @@ -133,7 +133,7 @@ const QString type = group.readEntry("Type").toLower(); if (type.isEmpty()) { - qCWarning(AKONADICORE_LOG) << "missing or empty [Plugin]Type value in \"" << entry << "\" - skipping" << endl; + qCWarning(AKONADICORE_LOG) << "missing or empty [Plugin]Type value in" << entry << "- skipping"; continue; } @@ -142,13 +142,13 @@ // and B>. const QStringList classes = group.readXdgListEntry("X-Akonadi-Class"); if (classes.isEmpty()) { - qCWarning(AKONADICORE_LOG) << "missing or empty [Plugin]X-Akonadi-Class value in \"" << entry << "\" - skipping" << endl; + qCWarning(AKONADICORE_LOG) << "missing or empty [Plugin]X-Akonadi-Class value in" << entry << "- skipping"; continue; } const QString library = group.readEntry("X-KDE-Library"); if (library.isEmpty()) { - qCWarning(AKONADICORE_LOG) << "missing or empty [Plugin]X-KDE-Library value in \"" << entry << "\" - skipping" << endl; + qCWarning(AKONADICORE_LOG) << "missing or empty [Plugin]X-KDE-Library value in" << entry << "- skipping"; continue; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/server/connection.cpp new/akonadi-16.04.2/src/server/connection.cpp --- old/akonadi-16.04.1/src/server/connection.cpp 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/server/connection.cpp 2016-05-31 11:33:56.000000000 +0200 @@ -429,6 +429,9 @@ Protocol::Command Connection::readCommand() { while (m_socket->bytesAvailable() < (int) sizeof(qint64)) { + if (m_socket->state() == QLocalSocket::UnconnectedState) { + return Protocol::Command(); + } m_socket->waitForReadyRead(500); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/server/storage/akonadidb.xml new/akonadi-16.04.2/src/server/storage/akonadidb.xml --- old/akonadi-16.04.1/src/server/storage/akonadidb.xml 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/server/storage/akonadidb.xml 2016-05-31 11:33:56.000000000 +0200 @@ -66,7 +66,7 @@ <table name="SchemaVersion"> <comment>Contains the schema version of the database.</comment> <column name="version" type="int" default="0" allowNull="false"/> - <data columns="version" values="31"/> + <data columns="version" values="32"/> </table> <table name="Resource"> @@ -126,7 +126,7 @@ <column name="datetime" type="QDateTime" default="QDateTime::currentDateTime()"> <comment>create/modified time</comment> </column> - <column name="atime" type="QDateTime"> + <column name="atime" type="QDateTime" default="QDateTime::currentDateTime()"> <comment>read access time</comment> </column> <column name="dirty" type="bool"> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/server/storage/dbconfig.cpp new/akonadi-16.04.2/src/server/storage/dbconfig.cpp --- old/akonadi-16.04.1/src/server/storage/dbconfig.cpp 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/server/storage/dbconfig.cpp 2016-05-31 11:33:56.000000000 +0200 @@ -30,6 +30,7 @@ #include <QtCore/QDir> #include <QtCore/QStringBuilder> +#include <QProcess> using namespace Akonadi; using namespace Akonadi::Server; @@ -136,3 +137,9 @@ { Q_UNUSED(database); } + +int DbConfig::execute(const QString &cmd, const QStringList &args) const +{ + akDebug() << "Executing: " << cmd << args.join(QLatin1Char(' ')); + return QProcess::execute(cmd, args); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/server/storage/dbconfig.h new/akonadi-16.04.2/src/server/storage/dbconfig.h --- old/akonadi-16.04.1/src/server/storage/dbconfig.h 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/server/storage/dbconfig.h 2016-05-31 11:33:56.000000000 +0200 @@ -116,6 +116,10 @@ */ static QString defaultDatabaseName(); + /** + * Calls QProcess::execute() and also prints the command and arguments via qCDebug() + */ + int execute(const QString &cmd, const QStringList &args) const; private: qint64 mSizeThreshold; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/server/storage/dbconfigmysql.cpp new/akonadi-16.04.2/src/server/storage/dbconfigmysql.cpp --- old/akonadi-16.04.1/src/server/storage/dbconfigmysql.cpp 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/server/storage/dbconfigmysql.cpp 2016-05-31 11:33:56.000000000 +0200 @@ -29,6 +29,7 @@ #include <QtCore/QDir> #include <QtCore/QProcess> #include <QtCore/QThread> +#include <QRegularExpression> #include <QtSql/QSqlDriver> #include <QtSql/QSqlError> #include <QtSql/QSqlQuery> @@ -39,6 +40,8 @@ #define MYSQL_MIN_MAJOR 5 #define MYSQL_MIN_MINOR 1 +#define MYSQL_VERSION_CHECK(major, minor, patch) ((major << 16) | (minor << 8) | patch) + DbConfigMysql::DbConfigMysql() : mInternalServer(true) , mDatabaseProcess(0) @@ -115,7 +118,7 @@ mUserName = settings.value(QStringLiteral("User")).toString(); mPassword = settings.value(QStringLiteral("Password")).toString(); mConnectionOptions = settings.value(QStringLiteral("Options"), defaultOptions).toString(); - mServerPath = settings.value(QStringLiteral("ServerPath"), defaultServerPath).toString(); + mMysqldPath = settings.value(QStringLiteral("ServerPath"), defaultServerPath).toString(); mCleanServerShutdownCommand = settings.value(QStringLiteral("CleanServerShutdownCommand"), defaultCleanShutdownCommand).toString(); settings.endGroup(); @@ -125,17 +128,19 @@ // intentionally not namespaced as we are the only one in this db instance when using internal mode mDatabaseName = QStringLiteral("akonadi"); } - if (mInternalServer && (mServerPath.isEmpty() || !QFile::exists(mServerPath))) { - mServerPath = defaultServerPath; + if (mInternalServer && (mMysqldPath.isEmpty() || !QFile::exists(mMysqldPath))) { + mMysqldPath = defaultServerPath; } + akDebug() << "Using mysqld:" << mMysqldPath; + // store back the default values settings.beginGroup(driverName()); settings.setValue(QStringLiteral("Name"), mDatabaseName); settings.setValue(QStringLiteral("Host"), mHostName); settings.setValue(QStringLiteral("Options"), mConnectionOptions); - if (!mServerPath.isEmpty()) { - settings.setValue(QStringLiteral("ServerPath"), mServerPath); + if (!mMysqldPath.isEmpty()) { + settings.setValue(QStringLiteral("ServerPath"), mMysqldPath); } settings.setValue(QStringLiteral("StartServer"), mInternalServer); settings.endGroup(); @@ -180,7 +185,6 @@ bool DbConfigMysql::startInternalServer() { bool success = true; - const QString mysqldPath = mServerPath; const QString akDir = StandardDirs::saveDir("data"); const QString dataDir = StandardDirs::saveDir("data", QStringLiteral("db_data")); @@ -209,6 +213,26 @@ } #endif + if (mMysqldPath.isEmpty()) { + akError() << "mysqld not found. Please verify your installation"; + return false; + } + + // Get the version of the mysqld server that we'll be using. + // MySQL (but not MariaDB) deprecates and removes command line options in + // patch version releases, so we need to adjust the command line options accordingly + // when running the helper utilities or starting the server + const unsigned int localVersion = parseCommandLineToolsVersion(); + if (localVersion == 0x000000) { + akError() << "Failed to detect mysqld version!"; + } + // TODO: Parse "MariaDB" or "MySQL" from the version string instead of relying + // on the version numbers + const bool isMariaDB = localVersion >= MYSQL_VERSION_CHECK(10, 0, 0); + akDebug().nospace() << "mysqld reports version " << (localVersion >> 16) << "." << ((localVersion >> 8) & 0x0000FF) << "." << (localVersion & 0x0000FF) + << " (" << (isMariaDB ? "MariaDB" : "Oracle MySQL") << ")"; + + bool confUpdate = false; QFile actualFile(actualConfig); // update conf only if either global (or local) is newer than actual @@ -285,8 +309,13 @@ // first run, some MySQL versions need a mysql_install_db run for that const QString confFile = XdgBaseDirs::findResourceFile("config", QStringLiteral("akonadi/mysql-global.conf")); if (QDir(dataDir).entryList(QDir::NoDotAndDotDot | QDir::AllEntries).isEmpty() && !mMysqlInstallDbPath.isEmpty()) { - const QStringList arguments = QStringList() << QStringLiteral("--force") << QStringLiteral("--defaults-file=%1").arg(confFile) << QStringLiteral("--datadir=%1/").arg(dataDir); - QProcess::execute(mMysqlInstallDbPath, arguments); + if (isMariaDB) { + initializeMariaDBDatabase(confFile, dataDir); + } else if (localVersion >= MYSQL_VERSION_CHECK(5, 7, 6)) { + initializeMySQL5_7_6Database(confFile, dataDir); + } else { + initializeMySQLDatabase(confFile, dataDir); + } } // clear mysql ib_logfile's in case innodb_log_file_size option changed in last confUpdate @@ -305,15 +334,12 @@ arguments << QString::fromLatin1("--shared-memory"); #endif - if (mysqldPath.isEmpty()) { - akError() << "mysqld not found. Please verify your installation"; - return false; - } + akDebug() << "Executing:" << mMysqldPath << arguments.join(QLatin1Char(' ')); mDatabaseProcess = new QProcess; - mDatabaseProcess->start(mysqldPath, arguments); + mDatabaseProcess->start(mMysqldPath, arguments); if (!mDatabaseProcess->waitForStarted()) { akError() << "Could not start database server!"; - akError() << "executable:" << mysqldPath; + akError() << "executable:" << mMysqldPath; akError() << "arguments:" << arguments; akError() << "process error:" << mDatabaseProcess->errorString(); return false; @@ -347,7 +373,7 @@ } if (mDatabaseProcess->waitForFinished(500)) { akError() << "Database process exited unexpectedly during initial connection!"; - akError() << "executable:" << mysqldPath; + akError() << "executable:" << mMysqldPath; akError() << "arguments:" << arguments; akError() << "stdout:" << mDatabaseProcess->readAllStandardOutput(); akError() << "stderr:" << mDatabaseProcess->readAllStandardError(); @@ -359,15 +385,14 @@ if (opened) { if (!mMysqlCheckPath.isEmpty()) { - const QStringList arguments = QStringList() << QStringLiteral("--defaults-file=%1/mysql.conf").arg(akDir) - << QStringLiteral("--check-upgrade") - << QStringLiteral("--all-databases") - << QStringLiteral("--auto-repair") + execute(mMysqlCheckPath, { QStringLiteral("--defaults-file=%1/mysql.conf").arg(akDir), + QStringLiteral("--check-upgrade"), + QStringLiteral("--auto-repair"), #ifndef Q_OS_WIN - << QStringLiteral("--socket=%1/mysql.socket").arg(socketDirectory) + QStringLiteral("--socket=%1/mysql.socket").arg(socketDirectory), #endif - ; - QProcess::execute(mMysqlCheckPath, arguments); + mDatabaseName + }); } // Verify MySQL version @@ -454,3 +479,47 @@ QSqlQuery query(database); query.exec(QStringLiteral("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")); } + +int DbConfigMysql::parseCommandLineToolsVersion() const +{ + QProcess mysqldProcess; + mysqldProcess.start(mMysqldPath, { QStringLiteral("--version") }); + mysqldProcess.waitForFinished(10000 /* 10 secs */); + + const QString out = QString::fromLocal8Bit(mysqldProcess.readAllStandardOutput()); + QRegularExpression regexp(QStringLiteral("Ver ([0-9]+)\\.([0-9]+)\\.([0-9]+)")); + auto match = regexp.match(out); + if (!match.hasMatch()) { + return 0; + } + + return (match.capturedRef(1).toInt() << 16) | (match.capturedRef(2).toInt() << 8) | match.capturedRef(3).toInt(); +} + +bool DbConfigMysql::initializeMariaDBDatabase(const QString &confFile, const QString &dataDir) const +{ + return 0 == execute(mMysqlInstallDbPath, + { QStringLiteral("--defaults-file=%1").arg(confFile), + QStringLiteral("--force"), + QStringLiteral("--datadir=%1/").arg(dataDir) }); +} + +/** + * As of MySQL 5.7.6 mysql_install_db is deprecated and mysqld --initailize should be used instead + * See MySQL Reference Manual section 2.10.1.1 (Initializing the Data Directory Manually Using mysqld) + */ +bool DbConfigMysql::initializeMySQL5_7_6Database(const QString &confFile, const QString &dataDir) const +{ + return 0 == execute(mMysqldPath, + { QStringLiteral("--defaults-file=%1").arg(confFile), + QStringLiteral("--initialize"), + QStringLiteral("--datadir=%1/").arg(dataDir) }); +} + +bool DbConfigMysql::initializeMySQLDatabase(const QString &confFile, const QString &dataDir) const +{ + // Don't use --force, it has been removed in MySQL 5.7.5 + return 0 == execute(mMysqlInstallDbPath, + { QStringLiteral("--defaults-file=%1").arg(confFile), + QStringLiteral("--datadir=%1/").arg(dataDir) }); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/server/storage/dbconfigmysql.h new/akonadi-16.04.2/src/server/storage/dbconfigmysql.h --- old/akonadi-16.04.1/src/server/storage/dbconfigmysql.h 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/server/storage/dbconfigmysql.h 2016-05-31 11:33:56.000000000 +0200 @@ -76,12 +76,18 @@ virtual void initSession(const QSqlDatabase &database); private: + int parseCommandLineToolsVersion() const; + + bool initializeMariaDBDatabase(const QString &confFile, const QString &dataDir) const; + bool initializeMySQL5_7_6Database(const QString &confFile, const QString &dataDir) const; + bool initializeMySQLDatabase(const QString &confFile, const QString &dataDir) const; + QString mDatabaseName; QString mHostName; QString mUserName; QString mPassword; QString mConnectionOptions; - QString mServerPath; + QString mMysqldPath; QString mCleanServerShutdownCommand; QString mMysqlInstallDbPath; QString mMysqlCheckPath; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/server/storage/dbconfigpostgresql.cpp new/akonadi-16.04.2/src/server/storage/dbconfigpostgresql.cpp --- old/akonadi-16.04.1/src/server/storage/dbconfigpostgresql.cpp 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/server/storage/dbconfigpostgresql.cpp 2016-05-31 11:33:56.000000000 +0200 @@ -80,12 +80,23 @@ } #endif postgresSearchPath << QStringLiteral("/usr/sbin") - << QStringLiteral("/usr/local/sbin") - << QStringLiteral("/usr/lib/postgresql/8.4/bin") - << QStringLiteral("/usr/lib/postgresql/9.0/bin") - << QStringLiteral("/usr/lib/postgresql/9.1/bin") - << QStringLiteral("/usr/lib/postgresql/9.2/bin") - << QStringLiteral("/usr/lib/postgresql/9.3/bin"); + << QStringLiteral("/usr/local/sbin"); + // Locale all versions in /usr/lib/postgresql (i.e. /usr/lib/postgresql/X.Y) in reversed + // sorted order, so we search from the newest one to the oldest. + QStringList postgresVersionedSearchPaths; + QDir versionedDir(QStringLiteral("/usr/lib/postgresql")); + if (versionedDir.exists()) { + const auto versionedDirs = versionedDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); + Q_FOREACH (const auto &path, versionedDirs) { + // Don't break once PostgreSQL 10 is released, but something more future-proof will be needed + if (path.fileName().startsWith(QLatin1String("10."))) { + postgresVersionedSearchPaths.prepend(path.absoluteFilePath() + QStringLiteral("/bin")); + } else { + postgresVersionedSearchPaths.append(path.absoluteFilePath() + QStringLiteral("/bin")); + } + } + } + postgresSearchPath.append(postgresVersionedSearchPaths); defaultServerPath = XdgBaseDirs::findExecutableFile(QStringLiteral("pg_ctl"), postgresSearchPath); defaultInitDbPath = XdgBaseDirs::findExecutableFile(QStringLiteral("initdb"), postgresSearchPath); @@ -112,10 +123,12 @@ if (mInternalServer && mServerPath.isEmpty()) { mServerPath = defaultServerPath; } + akDebug() << "Found pg_ctl:" << mServerPath; mInitDbPath = settings.value(QStringLiteral("InitDbPath"), defaultInitDbPath).toString(); if (mInternalServer && mInitDbPath.isEmpty()) { mInitDbPath = defaultInitDbPath; } + akDebug() << "Found initdb:" << mServerPath; mPgData = settings.value(QStringLiteral("PgData"), defaultPgData).toString(); if (mPgData.isEmpty()) { mPgData = defaultPgData; @@ -228,12 +241,9 @@ #endif // call 'initdb --pgdata=/home/user/.local/share/akonadi/data_db' - const QString command = QStringLiteral("%1").arg(mInitDbPath); - QStringList arguments; - arguments << QStringLiteral("--pgdata=%2").arg(mPgData) - // TODO check locale - << QStringLiteral("--locale=en_US.UTF-8"); - QProcess::execute(command, arguments); + execute(mInitDbPath, { QStringLiteral("--pgdata=%1").arg(mPgData), + QStringLiteral("--locale=en_US.UTF-8") // TODO: check locale + }); } // synthesize the postgres command @@ -247,6 +257,7 @@ // -h - disable listening for TCP/IP << QStringLiteral("-o \"-k%1\" -h ''").arg(socketDir); + akDebug() << "Executing:" << mServerPath << arguments.join(QLatin1Char(' ')); QProcess pgCtl; pgCtl.start(mServerPath, arguments); if (!pgCtl.waitForStarted()) { @@ -309,6 +320,8 @@ db.close(); } } + // Make sure pg_ctl has returned + pgCtl.waitForFinished(); QSqlDatabase::removeDatabase(initCon); return success; @@ -321,24 +334,18 @@ return; } - const QString command = QStringLiteral("%1").arg(mServerPath); - // first, try a FAST shutdown - QStringList arguments; - arguments << QStringLiteral("stop") - << QStringLiteral("--pgdata=%1").arg(mPgData) - << QStringLiteral("--mode=fast"); - QProcess::execute(command, arguments); + execute(mServerPath, { QStringLiteral("stop"), + QStringLiteral("--pgdata=%1").arg(mPgData), + QStringLiteral("--mode=fast") }); if (!checkServerIsRunning()) { return; } // second, try an IMMEDIATE shutdown - arguments.clear(); - arguments << QStringLiteral("stop") - << QStringLiteral("--pgdata=%1").arg(mPgData) - << QStringLiteral("--mode=immediate"); - QProcess::execute(command, arguments); + execute(mServerPath, { QStringLiteral("stop"), + QStringLiteral("--pgdata=%1").arg(mPgData), + QStringLiteral("--mode=immediate") }); if (!checkServerIsRunning()) { return; } @@ -353,11 +360,9 @@ QString postmasterPid = QString::fromUtf8(pidFile.readLine(0).trimmed()); akError() << "The postmaster is still running. Killing it."; - arguments.clear(); - arguments << QStringLiteral("kill") - << QStringLiteral("ABRT") - << QStringLiteral("%1").arg(postmasterPid); - QProcess::execute(command, arguments); + execute(mServerPath, { QStringLiteral("kill"), + QStringLiteral("ABRT"), + postmasterPid }); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/server/utils.cpp new/akonadi-16.04.2/src/server/utils.cpp --- old/akonadi-16.04.1/src/server/utils.cpp 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/server/utils.cpp 2016-05-31 11:33:56.000000000 +0200 @@ -74,9 +74,11 @@ socketDir = serverSettings.value(QStringLiteral("Connection/SocketDirectory"), defaultDirectory).toString(); } - const QString userName = QString::fromLocal8Bit(qgetenv("USER")); - if (socketDir.contains(QLatin1String("$USER")) && !userName.isEmpty()) { - socketDir.replace(QLatin1String("$USER"), userName); + if (socketDir.contains(QLatin1String("$USER"))) { + const QString userName = QString::fromLocal8Bit(qgetenv("USER")); + if (!userName.isEmpty()) { + socketDir.replace(QLatin1String("$USER"), userName); + } } if (socketDir[0] != QLatin1Char('/')) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/widgets/collectionstatisticsdelegate.cpp new/akonadi-16.04.2/src/widgets/collectionstatisticsdelegate.cpp --- old/akonadi-16.04.1/src/widgets/collectionstatisticsdelegate.cpp 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/widgets/collectionstatisticsdelegate.cpp 2016-05-31 11:33:56.000000000 +0200 @@ -313,8 +313,9 @@ } else if (option.decorationPosition == QStyleOptionViewItem::Top) { if (unreadCount > 0) { // draw over the icon + // the iconRect is enlarged to the whole width of the item, in case the text is wider than the underlying icon painter->setPen(unreadColor); - painter->drawText(iconRect, Qt::AlignCenter, QString::number(unreadCount)); + painter->drawText(QRect(option.rect.x(), iconRect.y(), option.rect.width(), iconRect.height()), Qt::AlignCenter, QString::number(unreadCount)); } } return; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/akonadi-16.04.1/src/widgets/tageditwidget.cpp new/akonadi-16.04.2/src/widgets/tageditwidget.cpp --- old/akonadi-16.04.1/src/widgets/tageditwidget.cpp 2016-05-02 14:03:47.000000000 +0200 +++ new/akonadi-16.04.2/src/widgets/tageditwidget.cpp 2016-05-31 11:33:56.000000000 +0200 @@ -192,6 +192,7 @@ , d(new Private(model, this)) { QVBoxLayout *topLayout = new QVBoxLayout(this); + topLayout->setMargin(0); QItemSelectionModel *selectionModel = new QItemSelectionModel(d->m_model, this); d->m_checkableProxy = new KCheckableProxyModel(this);
