From 5162328cd8edba85017185ef5864b2b65f6f18ed Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Sun, 8 May 2016 22:57:41 +0200 Subject: Move mimeMessage in preprocessor, and directly move to cur. We use the maildir as our internal storage, so the message needs to be moved immediately and not only with changereplay. --- examples/maildirresource/libmaildir/maildir.cpp | 4 +- examples/maildirresource/maildirresource.cpp | 76 ++++++++++++++++++++++--- tests/maildirresourcetest.cpp | 12 ++-- 3 files changed, 76 insertions(+), 16 deletions(-) diff --git a/examples/maildirresource/libmaildir/maildir.cpp b/examples/maildirresource/libmaildir/maildir.cpp index 670d4ca..1018b4a 100644 --- a/examples/maildirresource/libmaildir/maildir.cpp +++ b/examples/maildirresource/libmaildir/maildir.cpp @@ -729,8 +729,8 @@ QString Maildir::addEntryFromPath(const QString& path) return QString(); } - if (!f.rename(finalKey)) { - qWarning() << "Maildir: Failed to add entry: " << finalKey << "! Error: " << f.errorString(); + if (!f.rename(curKey)) { + qWarning() << "Maildir: Failed to add entry: " << curKey << "! Error: " << f.errorString(); // d->lastError = i18n("Failed to create mail file %1. The error was: %2" , finalKey, f.errorString()); return QString(); } diff --git a/examples/maildirresource/maildirresource.cpp b/examples/maildirresource/maildirresource.cpp index f4833a8..caebd47 100644 --- a/examples/maildirresource/maildirresource.cpp +++ b/examples/maildirresource/maildirresource.cpp @@ -54,11 +54,44 @@ class FolderUpdater : public Sink::Preprocessor public: FolderUpdater(const QByteArray &drafts) : mDraftsFolder(drafts) {} + QString getPath(const QByteArray &folderIdentifier, Sink::Storage::Transaction &transaction) + { + if (folderIdentifier.isEmpty()) { + return mMaildirPath; + } + QString folderPath; + auto db = Sink::Storage::mainDatabase(transaction, ENTITY_TYPE_FOLDER); + db.findLatest(folderIdentifier, [&](const QByteArray &, const QByteArray &value) { + Sink::EntityBuffer buffer(value); + const Sink::Entity &entity = buffer.entity(); + const auto adaptor = mFolderAdaptorFactory->createAdaptor(entity); + auto folderName = adaptor->getProperty("name").toString(); + //TODO handle non toplevel folders + folderPath = mMaildirPath + "/" + folderName; + }); + return folderPath; + } + void newEntity(const QByteArray &uid, qint64 revision, Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE { if (newEntity.getProperty("draft").toBool()) { newEntity.setProperty("folder", mDraftsFolder); } + const auto mimeMessage = newEntity.getProperty("mimeMessage"); + if (mimeMessage.isValid()) { + const auto oldPath = newEntity.getProperty("mimeMessage").toString(); + if (oldPath.startsWith(Sink::temporaryFileLocation())) { + auto folder = newEntity.getProperty("folder").toByteArray(); + const auto path = getPath(folder, transaction); + KPIM::Maildir maildir(path, false); + if (!maildir.isValid(true)) { + qWarning() << "Maildir is not existing: " << path; + } + auto identifier = maildir.addEntryFromPath(oldPath); + auto newPath = path + "/cur/" + identifier; + newEntity.setProperty("mimeMessage", QVariant::fromValue(newPath)); + } + } } void modifiedEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, Sink::ApplicationDomain::BufferAdaptor &newEntity, @@ -70,6 +103,33 @@ public: { } QByteArray mDraftsFolder; + QByteArray mResourceInstanceIdentifier; + QString mMaildirPath; + QSharedPointer mFolderAdaptorFactory; +}; + +class FolderPreprocessor : public Sink::Preprocessor +{ +public: + FolderPreprocessor() {} + + void newEntity(const QByteArray &uid, qint64 revision, Sink::ApplicationDomain::BufferAdaptor &newEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE + { + auto folderName = newEntity.getProperty("name").toString(); + const auto path = mMaildirPath + "/" + folderName; + KPIM::Maildir maildir(path, false); + maildir.create(); + } + + void modifiedEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, Sink::ApplicationDomain::BufferAdaptor &newEntity, + Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE + { + } + + void deletedEntity(const QByteArray &uid, qint64 revision, const Sink::ApplicationDomain::BufferAdaptor &oldEntity, Sink::Storage::Transaction &transaction) Q_DECL_OVERRIDE + { + } + QString mMaildirPath; }; MaildirResource::MaildirResource(const QByteArray &instanceIdentifier, const QSharedPointer &pipeline) @@ -87,8 +147,9 @@ MaildirResource::MaildirResource(const QByteArray &instanceIdentifier, const QSh auto folderUpdater = new FolderUpdater(QByteArray()); addType(ENTITY_TYPE_MAIL, mMailAdaptorFactory, QVector() << new DefaultIndexUpdater << folderUpdater); + auto folderPreprocessor = new FolderPreprocessor; addType(ENTITY_TYPE_FOLDER, mFolderAdaptorFactory, - QVector() << new DefaultIndexUpdater); + QVector() << new DefaultIndexUpdater << folderPreprocessor); KPIM::Maildir dir(mMaildirPath, true); mDraftsFolder = dir.addSubFolder("drafts"); @@ -103,6 +164,10 @@ MaildirResource::MaildirResource(const QByteArray &instanceIdentifier, const QSh synchronizationTransaction.commit(); folderUpdater->mDraftsFolder = draftsFolderLocalId; + folderUpdater->mResourceInstanceIdentifier = mResourceInstanceIdentifier; + folderUpdater->mFolderAdaptorFactory = mFolderAdaptorFactory; + folderUpdater->mMaildirPath = mMaildirPath; + folderPreprocessor->mMaildirPath = mMaildirPath; } static QStringList listRecursive( const QString &root, const KPIM::Maildir &dir ) @@ -321,13 +386,8 @@ KAsync::Job MaildirResource::replay(Sink::Storage &synchronizationStore, c parentFolderRemoteId = mMaildirPath.toUtf8(); } const auto parentFolderPath = parentFolderRemoteId; - KPIM::Maildir maildir(parentFolderPath, false); - if (!maildir.isValid(true)) { - return KAsync::error(1, "Invalid folder " + parentFolderPath); - } - //FIXME move the mime message from the mimeMessage property to the proper place. - Trace() << "Creating a new mail."; - const auto remoteId = maildir.addEntryFromPath(mail.getProperty("mimeMessage").toString()); + const auto remoteId = mail.getProperty("mimeMessage").toString().split('/').last(); + Trace() << "Creating a new mail." << remoteId; if (remoteId.isEmpty()) { Warning() << "Failed to create mail: " << remoteId; return KAsync::error(1, "Failed to create mail."); diff --git a/tests/maildirresourcetest.cpp b/tests/maildirresourcetest.cpp index 372ca5d..ec685a6 100644 --- a/tests/maildirresourcetest.cpp +++ b/tests/maildirresourcetest.cpp @@ -196,7 +196,7 @@ private slots: auto model = Sink::Store::loadModel(query); QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool()); - QCOMPARE(model->rowCount(QModelIndex()), 3); + QCOMPARE(model->rowCount(QModelIndex()), 4); QCOMPARE(model->match(model->index(0, 0, QModelIndex()), Qt::DisplayRole, QStringLiteral("newbox"), 1).size(), 1); } @@ -312,11 +312,11 @@ private slots: // Ensure all local data is processed Sink::ResourceControl::flushMessageQueue(query.resources).exec().waitForFinished(); - auto targetPath = tempDir.path() + "/maildir1/new"; + auto targetPath = tempDir.path() + "/maildir1/cur"; QDir dir(targetPath); dir.setFilter(QDir::Files); - QTRY_COMPARE(dir.count(), static_cast(1)); - QFile file(targetPath + "/" + dir.entryList().first()); + QTRY_COMPARE(dir.count(), static_cast(2)); + QFile file(targetPath + "/" + dir.entryList().last()); QVERIFY(file.open(QIODevice::ReadOnly)); KMime::Message m; m.setContent(file.readAll()); @@ -360,10 +360,10 @@ private slots: future2.waitForFinished(); QVERIFY(!future2.errorCode()); - auto targetPath = tempDir.path() + "/maildir1/newfolder/new"; + auto targetPath = tempDir.path() + "/maildir1/newfolder/cur"; QDir dir(targetPath); dir.setFilter(QDir::Files); - QTRY_COMPARE(dir.count(), static_cast(1)); + QCOMPARE(dir.count(), static_cast(1)); } void testRemoveMail() -- cgit v1.2.3