Branch 'kolab/integration/4.13.0' - 4 commits - resources/kolab

Christian Mollekopf mollekopf at kolabsys.com
Thu Jan 8 17:12:14 CET 2015


 resources/kolab/CMakeLists.txt                   |    1 
 resources/kolab/kolabchangeitemstagstask.cpp     |   14 -
 resources/kolab/kolabchangetagtask.cpp           |    8 
 resources/kolab/kolabretrievecollectionstask.cpp |    1 
 resources/kolab/tagchangehelper.cpp              |   41 ----
 resources/kolab/updatemessagejob.cpp             |  233 +++++++++++++++++++++++
 resources/kolab/updatemessagejob.h               |   84 ++++++++
 7 files changed, 337 insertions(+), 45 deletions(-)

New commits:
commit b27e0473d334602a52c3cf9b2e6e6661b5cffad2
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Thu Jan 8 17:11:58 2015 +0100

    Revert "Filter tag items by resource."
    
    This reverts commit c9761baf173a01ce4a1f8e6cfccc7d7b4b45690c.
    
    This didn't work and is now done in the akonadi server.
    
    Conflicts:
    	resources/kolab/kolabchangeitemstagstask.cpp

diff --git a/resources/kolab/kolabchangeitemstagstask.cpp b/resources/kolab/kolabchangeitemstagstask.cpp
index 785664d..cf1564b 100644
--- a/resources/kolab/kolabchangeitemstagstask.cpp
+++ b/resources/kolab/kolabchangeitemstagstask.cpp
@@ -103,13 +103,7 @@ void KolabChangeItemsTagsTask::onItemsFetchDone(KJob *job)
         return;
     }
 
-    Akonadi::Item::List items;
-    //Filter by resource as all other references make no sense
-    Q_FOREACH (const Akonadi::Item &i, static_cast<Akonadi::ItemFetchJob*>(job)->items()) {
-        if (i.parentCollection().resource() == resourceState()->resourceIdentifier()) {
-            items << i;
-        }
-    }
+    const Akonadi::Item::List items = static_cast<Akonadi::ItemFetchJob*>(job)->items();
     kDebug() << items.size();
 
     TagChangeHelper *changeHelper = new TagChangeHelper(this);
diff --git a/resources/kolab/kolabchangetagtask.cpp b/resources/kolab/kolabchangetagtask.cpp
index e6b31ad..f58e85d 100644
--- a/resources/kolab/kolabchangetagtask.cpp
+++ b/resources/kolab/kolabchangetagtask.cpp
@@ -52,13 +52,7 @@ void KolabChangeTagTask::onItemsFetchDone(KJob *job)
         return;
     }
 
-    Akonadi::Item::List items;
-    //Filter by resource as all other references make no sense
-    Q_FOREACH (const Akonadi::Item &i, static_cast<Akonadi::ItemFetchJob*>(job)->items()) {
-        if (i.parentCollection().resource() == resourceState()->resourceIdentifier()) {
-            items << i;
-        }
-    }
+    const Akonadi::Item::List items = static_cast<Akonadi::ItemFetchJob*>(job)->items();
 
     TagChangeHelper *changeHelper = new TagChangeHelper(this);
 


commit c4444aa93b5ff32c55b12421eaec93ba756b5b71
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Thu Jan 8 17:10:36 2015 +0100

    Debug info for tags.

diff --git a/resources/kolab/kolabchangeitemstagstask.cpp b/resources/kolab/kolabchangeitemstagstask.cpp
index 21269fe..785664d 100644
--- a/resources/kolab/kolabchangeitemstagstask.cpp
+++ b/resources/kolab/kolabchangeitemstagstask.cpp
@@ -120,6 +120,12 @@ void KolabChangeItemsTagsTask::onItemsFetchDone(KJob *job)
     connect(changeHelper, SIGNAL(changeCommitted()), this, SLOT(onChangeCommitted()));
 
     const Akonadi::Tag tag = job->property("tag").value<Akonadi::Tag>();
+    {
+        kDebug() << "Writing " << tag.name() << " with " << items.size() << " members to the server: ";
+        foreach (const Akonadi::Item &item, items) {
+            kDebug() << "member(localid, remoteid): " << item.id() << item.remoteId();
+        }
+    }
     Q_ASSERT(tag.isValid());
     changeHelper->start(tag, mTagConverter->createMessage(tag, items, resourceState()->userName()), mSession);
 }


commit d071f3ad1846a9d94f58af57aa5a76047c8594e5
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Thu Jan 8 17:10:25 2015 +0100

    UpdateMessageJob to prepare for tag merging.

diff --git a/resources/kolab/CMakeLists.txt b/resources/kolab/CMakeLists.txt
index 7dd587c..5e0a889 100644
--- a/resources/kolab/CMakeLists.txt
+++ b/resources/kolab/CMakeLists.txt
@@ -28,6 +28,7 @@ set(kolabresource_LIB_SRCS
     tagchangehelper.cpp
     kolabretrievetagstask.cpp
     kolabsettings.cpp
+    updatemessagejob.cpp
 )
 
 kde4_add_kcfg_files(kolabresource_LIB_SRCS ../imap/settingsbase.kcfgc)
diff --git a/resources/kolab/tagchangehelper.cpp b/resources/kolab/tagchangehelper.cpp
index 73e8c78..56d021a 100644
--- a/resources/kolab/tagchangehelper.cpp
+++ b/resources/kolab/tagchangehelper.cpp
@@ -23,6 +23,7 @@
 
 #include "kolabrelationresourcetask.h"
 #include "kolabhelpers.h"
+#include "updatemessagejob.h"
 
 #include <imapflags.h>
 #include <uidnextattribute.h>
@@ -62,6 +63,13 @@ KMime::Message::Ptr TagConverter::createMessage(const Akonadi::Tag &tag, const A
     return message;
 }
 
+struct TagMerger : public Merger {
+    virtual KMime::Message::Ptr merge(KMime::Message::Ptr newMessage, QList<KMime::Message::Ptr> conflictingMessages) const
+    {
+        return newMessage;
+    }
+};
+
 void TagChangeHelper::start(const Akonadi::Tag &tag, const KMime::Message::Ptr &message, KIMAP::Session *session)
 {
     Q_ASSERT(tag.isValid());
@@ -69,13 +77,9 @@ void TagChangeHelper::start(const Akonadi::Tag &tag, const KMime::Message::Ptr &
     const qint64 oldUid = tag.remoteId().toLongLong();
     kDebug(5327) << mailBox << oldUid;
 
-    qint64 uidNext = -1;
-    // Using uidnext here is mutually exclusive with doing the item sync
-    // if (UidNextAttribute *uidNextAttr = mTask->relationCollection().attribute<UidNextAttribute>()) {
-    //     uidNext = uidNextAttr->uidNext();
-    // }
+    const qint64 uidNext = -1;
 
-    ReplaceMessageJob *append = new ReplaceMessageJob(message, session, mailBox, uidNext, oldUid, this);
+    UpdateMessageJob *append = new UpdateMessageJob(message, session, tag.gid(), QSharedPointer<TagMerger>(new TagMerger), mailBox, uidNext, oldUid, this);
     connect(append, SIGNAL(result(KJob*)), this, SLOT(onReplaceDone(KJob*)));
     append->setProperty("tag", QVariant::fromValue(tag));
     append->start();
@@ -86,31 +90,6 @@ void TagChangeHelper::recordNewUid(qint64 newUid, Akonadi::Tag tag)
     Q_ASSERT(newUid > 0);
     Q_ASSERT(tag.isValid());
 
-    Akonadi::Collection c = mTask->relationCollection();
-
-    // Get the current uid next value and store it
-    // UidNextAttribute *uidAttr = 0;
-    // int oldNextUid = 0;
-    // if (c.hasAttribute("uidnext")) {
-    //     uidAttr = static_cast<UidNextAttribute*>(c.attribute("uidnext"));
-    //     oldNextUid = uidAttr->uidNext();
-    // }
-
-    // If the uid we just got back is the expected next one of the box
-    // then update the property to the probable next uid to keep the cache in sync.
-    // If not something happened in our back, so we don't update and a refetch will
-    // happen at some point.
-    // if (newUid == oldNextUid) {
-    //     if (uidAttr == 0) {
-    //         uidAttr = new UidNextAttribute(newUid + 1);
-    //         c.addAttribute(uidAttr);
-    //     } else {
-    //         uidAttr->setUidNext(newUid + 1);
-    //     }
-
-    //     emit applyCollectionChanges(c);
-    // }
-
     const QByteArray remoteId =  QByteArray::number(newUid);
     kDebug(5327) << "Setting remote ID to " << remoteId << " on tag with local id: " << tag.id();
     //Make sure we only update the id and send nothing else
diff --git a/resources/kolab/updatemessagejob.cpp b/resources/kolab/updatemessagejob.cpp
new file mode 100644
index 0000000..a5149e1
--- /dev/null
+++ b/resources/kolab/updatemessagejob.cpp
@@ -0,0 +1,233 @@
+/*
+    Copyright (c) 2014 Christian Mollekopf <mollekopf at kolabsys.com>
+
+    This library is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Library General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or (at your
+    option) any later version.
+
+    This library is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+    License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to the
+    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+*/
+
+#include "updatemessagejob.h"
+
+#include <KIMAP/AppendJob>
+#include <KIMAP/SearchJob>
+#include <KIMAP/SelectJob>
+#include <KIMAP/StoreJob>
+#include <KIMAP/FetchJob>
+#include <KIMAP/ImapSet>
+#include <KDebug>
+#include <KMime/Message>
+#include <replacemessagejob.h>
+
+#include "imapflags.h"
+
+//Check if the expected uid message is still there => no modification, replace message.
+//otherwise search for uptodate message by subject containing UID, merge contents, and replace message
+
+UpdateMessageJob::UpdateMessageJob(const KMime::Message::Ptr &msg, KIMAP::Session *session, const QByteArray &kolabUid, QSharedPointer<Merger> merger, const QString &mailbox, qint64 uidNext, qint64 oldUid, QObject *parent)
+    : KJob(parent),
+    mSession(session),
+    mMessage(msg),
+    mMailbox(mailbox),
+    mUidNext(uidNext),
+    mOldUid(oldUid),
+    mNewUid(-1),
+    mMessageId(msg->messageID()->asUnicodeString().toUtf8()),
+    mKolabUid(kolabUid),
+    mMerger(merger)
+{
+}
+
+void UpdateMessageJob::start()
+{
+    KIMAP::FetchJob * fetchJob = new KIMAP::FetchJob(mSession);
+
+    fetchJob->setSequenceSet(KIMAP::ImapSet(mOldUid));
+    fetchJob->setUidBased(true);
+
+    KIMAP::FetchJob::FetchScope scope;
+    scope.parts.clear();
+    scope.mode = KIMAP::FetchJob::FetchScope::Headers;
+    fetchJob->setScope(scope);
+
+    connect(fetchJob, SIGNAL(headersReceived(QString,
+                                          QMap<qint64,qint64>,
+                                          QMap<qint64,qint64>,
+                                          QMap<qint64,KIMAP::MessageAttribute>,
+                                          QMap<qint64,KIMAP::MessageFlags>,
+                                          QMap<qint64,KIMAP::MessagePtr>)),
+            this, SLOT(onHeadersReceived(QString,
+                                         QMap<qint64,qint64>,
+                                         QMap<qint64,qint64>,
+                                         QMap<qint64,KIMAP::MessageAttribute>,
+                                         QMap<qint64,KIMAP::MessageFlags>,
+                                         QMap<qint64,KIMAP::MessagePtr>)));
+    connect(fetchJob, SIGNAL(result(KJob*)),
+            this, SLOT(onHeadersFetchDone(KJob*)));
+    fetchJob->start();
+
+
+}
+
+void UpdateMessageJob::onHeadersReceived(QString,
+                                         QMap<qint64,qint64> uids,
+                                         QMap<qint64,qint64>,
+                                         QMap<qint64,KIMAP::MessageAttribute>,
+                                         QMap<qint64,KIMAP::MessageFlags> flags,
+                                         QMap<qint64,KIMAP::MessagePtr>)
+{
+    //Filter deleted messages
+    foreach (qint64 number, uids.keys()) { //krazy:exclude=foreach
+        // const KMime::Message::Ptr msg = messages[number];
+        if (!flags[number].contains(ImapFlags::Deleted)) {
+            mFoundUids << uids[number];
+        }
+    }
+}
+
+void UpdateMessageJob::onHeadersFetchDone(KJob *job)
+{
+    if (job->error()) {
+        kWarning() << "Failed to fetch message: " << job->errorString();
+    }
+    if (mFoundUids.size() >= 1) {
+        kDebug() << "Fast-forward update, replacing message.";
+        appendMessage();
+    } else {
+        if (mSession->selectedMailBox() != mMailbox) {
+            KIMAP::SelectJob *select = new KIMAP::SelectJob(mSession);
+            select->setMailBox(mMailbox);
+            connect(select, SIGNAL(result(KJob*)), this, SLOT(onSelectDone(KJob*)));
+            select->start();
+        } else {
+            searchForLatestVersion();
+        }
+    }
+}
+
+void UpdateMessageJob::onSelectDone(KJob *job)
+{
+    if (job->error()) {
+        kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
+        emitResult();
+    } else {
+        searchForLatestVersion();
+    }
+}
+
+void UpdateMessageJob::searchForLatestVersion()
+{
+    KIMAP::SearchJob *search = new KIMAP::SearchJob(mSession);
+    search->setUidBased(true);
+    search->setSearchLogic(KIMAP::SearchJob::And);
+    search->addSearchCriteria(KIMAP::SearchJob::Header, "Subject " + mKolabUid);
+    connect(search, SIGNAL(result(KJob*)),
+            this, SLOT(onSearchDone(KJob*)));
+    search->start();
+}
+
+void UpdateMessageJob::onSearchDone(KJob *job)
+{
+    if (job->error()) {
+        kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
+        emitResult();
+        return;
+    }
+
+    KIMAP::SearchJob *search = static_cast<KIMAP::SearchJob*>(job);
+
+    if (search->results().count() >= 1) {
+        mOldUid = search->results().first();
+        //TODO deal with all of them
+
+        KIMAP::FetchJob * fetchJob = new KIMAP::FetchJob(mSession);
+        fetchJob->setSequenceSet(KIMAP::ImapSet(mOldUid));
+        fetchJob->setUidBased(true);
+
+        KIMAP::FetchJob::FetchScope scope;
+        scope.parts.clear();
+        scope.mode = KIMAP::FetchJob::FetchScope::Full;
+        fetchJob->setScope(scope);
+
+        connect(fetchJob, SIGNAL(headersReceived(QString,
+                                            QMap<qint64,qint64>,
+                                            QMap<qint64,qint64>,
+                                            QMap<qint64,KIMAP::MessageAttribute>,
+                                            QMap<qint64,KIMAP::MessageFlags>,
+                                            QMap<qint64,KIMAP::MessagePtr>)),
+                this, SLOT(onConflictingMessagesReceived(QString,
+                                            QMap<qint64,qint64>,
+                                            QMap<qint64,qint64>,
+                                            QMap<qint64,KIMAP::MessageAttribute>,
+                                            QMap<qint64,KIMAP::MessageFlags>,
+                                            QMap<qint64,KIMAP::MessagePtr>)));
+        connect(fetchJob, SIGNAL(result(KJob*)),
+                this, SLOT(onConflictingMessageFetchDone(KJob*)));
+        fetchJob->start();
+    } else {
+        kWarning() << "failed to find latest version of object";
+        appendMessage();
+    }
+}
+
+void UpdateMessageJob::onConflictingMessagesReceived(QString,
+                                         QMap<qint64,qint64> uids,
+                                         QMap<qint64,qint64>,
+                                         QMap<qint64,KIMAP::MessageAttribute>,
+                                         QMap<qint64,KIMAP::MessageFlags> flags,
+                                         QMap<qint64,KIMAP::MessagePtr> messages)
+{
+    foreach (qint64 number, uids.keys()) { //krazy:exclude=foreach
+        if (!flags[number].contains(ImapFlags::Deleted)) {
+            mMessagesToMerge << messages[number];
+        }
+    }
+}
+
+void UpdateMessageJob::onConflictingMessageFetchDone(KJob *job)
+{
+    if (job->error()) {
+        kWarning() << "Failed to retrieve messages to merge: " << job->errorString();
+    }
+    mMessage = mMerger->merge(mMessage, mMessagesToMerge);
+    appendMessage();
+}
+
+void UpdateMessageJob::appendMessage()
+{
+    const qint64 uidNext = -1;
+    ReplaceMessageJob *replace = new ReplaceMessageJob(mMessage, mSession, mMailbox, uidNext, mOldUid, this);
+    connect(replace, SIGNAL(result(KJob*)), this, SLOT(onReplaceDone(KJob*)));
+    replace->start();
+}
+
+void UpdateMessageJob::onReplaceDone(KJob *job)
+{
+    if (job->error()) {
+        kWarning() << job->errorString();
+        setError(KJob::UserDefinedError);
+        emitResult();
+        return;
+    }
+    ReplaceMessageJob *replaceJob = static_cast<ReplaceMessageJob*>(job);
+    mNewUid = replaceJob->newUid();
+    emitResult();
+}
+
+qint64 UpdateMessageJob::newUid() const
+{
+    return mNewUid;
+}
+
diff --git a/resources/kolab/updatemessagejob.h b/resources/kolab/updatemessagejob.h
new file mode 100644
index 0000000..99ddc90
--- /dev/null
+++ b/resources/kolab/updatemessagejob.h
@@ -0,0 +1,84 @@
+/*
+    Copyright (c) 2014 Christian Mollekopf <mollekopf at kolabsys.com>
+
+    This library is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Library General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or (at your
+    option) any later version.
+
+    This library is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+    License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to the
+    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+    02110-1301, USA.
+*/
+
+#ifndef UPDATEMESSAGEJOB_H
+#define UPDATEMESSAGEJOB_H
+
+#include <KJob>
+#include <KMime/Message>
+#include <KIMAP/Session>
+#include <KIMAP/FetchJob>
+
+struct Merger {
+    virtual ~Merger() {}
+    virtual KMime::Message::Ptr merge(KMime::Message::Ptr newMessage, QList<KMime::Message::Ptr> conflictingMessages) const = 0;
+};
+
+/**
+ * This job appends a message, marks the old one as deleted, and returns the uid of the appended message.
+ */
+class UpdateMessageJob : public KJob
+{
+    Q_OBJECT
+public:
+    UpdateMessageJob(const KMime::Message::Ptr &msg, KIMAP::Session *session, const QByteArray &kolabUid, QSharedPointer<Merger> merger, const QString &mailbox, qint64 uidNext = -1, qint64 oldUid = -1, QObject *parent = 0);
+
+    qint64 newUid() const;
+
+    void start();
+
+private:
+    void searchForLatestVersion();
+    void appendMessage();
+
+private Q_SLOTS:
+    void onHeadersReceived(QString,
+                            QMap<qint64,qint64> uids,
+                            QMap<qint64,qint64>,
+                            QMap<qint64,KIMAP::MessageAttribute>,
+                            QMap<qint64,KIMAP::MessageFlags>,
+                            QMap<qint64,KIMAP::MessagePtr>);
+    void onHeadersFetchDone(KJob *job);
+    void onSelectDone(KJob *job);
+    void onSearchDone(KJob *job);
+    void onConflictingMessagesReceived(QString,
+                                        QMap<qint64,qint64> uids,
+                                        QMap<qint64,qint64>,
+                                        QMap<qint64,KIMAP::MessageAttribute>,
+                                        QMap<qint64,KIMAP::MessageFlags>,
+                                        QMap<qint64,KIMAP::MessagePtr>);
+    void onConflictingMessageFetchDone(KJob *job);
+    void onReplaceDone(KJob *job);
+
+private:
+    KIMAP::Session *mSession;
+    KMime::Message::Ptr mMessage;
+    const QString mMailbox;
+    qint64 mUidNext;
+    qint64 mOldUid;
+    qint64 mNewUid;
+    const QByteArray mMessageId;
+    const QByteArray mKolabUid;
+    QList<qint64> mFoundUids;
+    QList<KIMAP::MessagePtr> mMessagesToMerge;
+    QSharedPointer<Merger> mMerger;
+};
+
+#endif
+


commit 87c14b51e97e99e9554cd1dfc874f18b7aa53b60
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Thu Jan 8 14:11:41 2015 +0100

    Print mailbox where myrights failed.

diff --git a/resources/kolab/kolabretrievecollectionstask.cpp b/resources/kolab/kolabretrievecollectionstask.cpp
index 87956bc..353df77 100644
--- a/resources/kolab/kolabretrievecollectionstask.cpp
+++ b/resources/kolab/kolabretrievecollectionstask.cpp
@@ -157,6 +157,7 @@ void RetrieveMetadataJob::onRightsReceived( KJob *job )
     mJobs--;
     if ( job->error() ) {
         kWarning() << "MyRights failed: " << job->errorString();
+        kWarning() << "mailbox " << static_cast<KIMAP::MyRightsJob*>( job )->mailBox();
         setError(KJob::UserDefinedError);
         checkDone();
         return; // Well, no metadata for us then...




More information about the commits mailing list