[neon/kde/kdepim-runtime/Neon/unstable] debian/patches: try out dvratils's imap patch
Carlos De Maine
null at kde.org
Thu Jun 12 01:24:09 BST 2025
Git commit 7302fa9333295a99295a7ff0b9f5c5fdf07f5285 by Carlos De Maine.
Committed on 12/06/2025 at 00:24.
Pushed by carlosdem into branch 'Neon/unstable'.
try out dvratils's imap patch
A +285 -0 debian/patches/imap_avoid_doing_search.diff
A +1 -0 debian/patches/series
https://invent.kde.org/neon/kde/kdepim-runtime/-/commit/7302fa9333295a99295a7ff0b9f5c5fdf07f5285
diff --git a/debian/patches/imap_avoid_doing_search.diff b/debian/patches/imap_avoid_doing_search.diff
new file mode 100644
index 0000000..8d17197
--- /dev/null
+++ b/debian/patches/imap_avoid_doing_search.diff
@@ -0,0 +1,285 @@
+diff --git a/resources/imap/autotests/testretrieveitemstask.cpp b/resources/imap/autotests/testretrieveitemstask.cpp
+index 1ae9702828ad29d48d1655774e75301eb14fbef5..85ae77f79c39531bc8136d6bd4c272f99b8b6386 100644
+--- a/resources/imap/autotests/testretrieveitemstask.cpp
++++ b/resources/imap/autotests/testretrieveitemstask.cpp
+@@ -229,15 +229,12 @@ private Q_SLOTS:
+ "Test\r\n"
+ " )"
+ << "S: A000007 OK fetch done"
+- << "C: A000008 UID SEARCH UID 1:7"
+- << "S: * SEARCH 1 2 3 4 5 6 7"
+- << "S: A000008 OK search done"
+- << "C: A000009 UID FETCH 1:7 (FLAGS UID)"
++ << "C: A000008 FETCH 1:4 (FLAGS UID)"
+ << "S: * 1 FETCH"
+ << "S: * 2 FETCH"
+ << "S: * 3 FETCH"
+ << "S: * 4 FETCH"
+- << "S: A000009 OK fetch done";
++ << "S: A000008 OK fetch done";
+
+ callNames.clear();
+ callNames << QStringLiteral("itemsRetrievedIncremental") << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievedIncremental")
+@@ -260,10 +257,10 @@ private Q_SLOTS:
+ << "S: * 5 EXISTS"
+ << "S: * 0 RECENT"
+ << "S: * OK [ UIDVALIDITY 1149151135 ]"
+- << "S: * OK [ UIDNEXT 9 ]"
++ << "S: * OK [ UIDNEXT 10 ]"
+ << "S: * OK [ HIGHESTMODSEQ 123456789 ]"
+ << "S: A000005 OK select done"
+- << "C: A000006 UID SEARCH UID 8:9"
++ << "C: A000006 UID SEARCH UID 8:10"
+ << "S: * SEARCH 8 9"
+ << "S: A000006 OK search done"
+ << "C: A000007 UID FETCH 8:9 (RFC822.SIZE INTERNALDATE BODY.PEEK[] FLAGS UID)"
+@@ -284,17 +281,17 @@ private Q_SLOTS:
+ "Test\r\n"
+ " )"
+ << "S: A000007 OK fetch done"
+- << "C: A000008 UID SEARCH UID 1:7"
+- << "S: * SEARCH 1 2 3 4 5 6 7"
+- << "S: A000008 OK search done"
+- << "C: A000009 UID FETCH 1:7 (FLAGS UID)"
+- << "S: * 1 FETCH"
+- << "S: * 2 FETCH"
+- << "S: * 3 FETCH"
+- << "S: A000009 OK fetch done";
++ << "C: A000008 FETCH 1:5 (FLAGS UID)"
++ << "S: * 1 FETCH ( FLAGS (\\Seen) UID 1 )"
++ << "S: * 2 FETCH ( FLAGS (\\Seen) UID 2 )"
++ << "S: * 3 FETCH ( FLAGS (\\Seen) UID 3 )"
++ << "S: * 4 FETCH ( FLAGS (\\Seen) UID 8 )"
++ << "S: * 5 FETCH ( FLAGS (\\Seen) UID 9 )"
++ << "S: A000008 OK fetch done";
+
+ callNames.clear();
+- callNames << QStringLiteral("itemsRetrieved") << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievalDone");
++ callNames << QStringLiteral("itemsRetrieved") << QStringLiteral("itemsRetrieved") << QStringLiteral("applyCollectionChanges")
++ << QStringLiteral("itemsRetrievalDone");
+
+ // A new message has been added and an old one removed, we can't do an incremental update
+ QTest::newRow("uidnext changed, fetch new messages and list flags") << collection << scenario << callNames;
+@@ -414,11 +411,8 @@ private Q_SLOTS:
+ << "S: * OK [ UIDVALIDITY 1149151135 ]"
+ << "S: * OK [ UIDNEXT 9 ]"
+ << "S: A000005 OK select done"
+- << "C: A000006 UID SEARCH UID 1:9"
+- << "S: * SEARCH 1 2 3 4 5 6 7 8 9"
+- << "S: A000006 OK search done"
+- << "C: A000007 UID FETCH 1:9 (RFC822.SIZE INTERNALDATE BODY.PEEK[] FLAGS UID)"
+- << "S: * 1 FETCH ( FLAGS (\\Seen) UID 2321 INTERNALDATE \"29-Jun-2010 15:26:42 +0200\" "
++ << "C: A000006 FETCH 1 (RFC822.SIZE INTERNALDATE BODY.PEEK[] FLAGS UID)"
++ << "S: * 1 FETCH ( FLAGS (\\Seen) UID 8 INTERNALDATE \"29-Jun-2010 15:26:42 +0200\" "
+ "RFC822.SIZE 75 BODY[] {75}\r\n"
+ "From: Foo <foo at kde.org>\r\n"
+ "To: Bar <bar at kde.org>\r\n"
+@@ -426,7 +420,7 @@ private Q_SLOTS:
+ "\r\n"
+ "Test\r\n"
+ " )"
+- << "S: A000007 OK fetch done";
++ << "S: A000006 OK fetch done";
+
+ callNames.clear();
+ callNames << QStringLiteral("itemsRetrieved") << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievalDone");
+@@ -479,17 +473,23 @@ private Q_SLOTS:
+ " )"
+ // 4 more would follow but are excluded for clarity
+ << "S: A000008 OK fetch done"
+- << "C: A000009 UID SEARCH UID 1:104"
+- << "S: * SEARCH 1 2 99 100"
+- << "S: A000009 OK search done"
+- << "C: A000010 UID FETCH 1:2,99:100 (FLAGS UID)"
++ << "C: A000009 FETCH 1:100 (FLAGS UID)"
+ << "S: * 1 FETCH ( FLAGS (\\Seen) UID 1 )"
++ // 99 more would follow but are excluded for clarity
++ << "S: A000009 OK fetch done"
++ << "C: A000010 FETCH 101:104 (FLAGS UID)"
++ << "S: * 1 FETCH ( FLAGS (\\Seen) UID 101 )"
+ // 3 more would follow but are excluded for clarity
+ << "S: A000010 OK fetch done";
+
+ callNames.clear();
+- callNames << QStringLiteral("itemsRetrievedIncremental") << QStringLiteral("itemsRetrievedIncremental") << QStringLiteral("itemsRetrievedIncremental")
+- << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievedIncremental") << QStringLiteral("itemsRetrievalDone");
++ callNames << QStringLiteral("itemsRetrievedIncremental") // first batch of new messages
++ << QStringLiteral("itemsRetrievedIncremental") // second batch of new messages
++ << QStringLiteral("itemsRetrievedIncremental") // first batch of flags updates
++ << QStringLiteral("itemsRetrievedIncremental") // second batch of flags updates
++ << QStringLiteral("applyCollectionChanges") // retrieval done, apply collection changes
++ << QStringLiteral("itemsRetrievedIncremental") // final call to ensure incremental update
++ << QStringLiteral("itemsRetrievalDone"); // sync done, no more calls expected
+
+ QTest::newRow("test batch processing") << collection << scenario << callNames;
+
+@@ -514,15 +514,12 @@ private Q_SLOTS:
+ << "S: * OK [ UIDNEXT 9 ]"
+ << "S: * OK [ HIGHESTMODSEQ 123456789 ]"
+ << "S: A000005 OK select done"
+- << "C: A000006 UID SEARCH UID 1:9"
+- << "S: * SEARCH 1 2 3 4"
+- << "S: A000006 OK search done"
+- << "C: A000007 UID FETCH 1:4 (FLAGS UID)"
++ << "C: A000006 FETCH 1:4 (FLAGS UID)"
+ << "S: * 1 FETCH ( FLAGS (\\Seen) UID 1 )"
+ << "S: * 2 FETCH ( FLAGS (\\Seen) UID 2 )"
+ << "S: * 3 FETCH ( FLAGS (\\Seen) UID 3 )"
+ << "S: * 4 FETCH ( FLAGS (\\Seen) UID 4 )"
+- << "S: A000007 OK fetch done";
++ << "S: A000006 OK fetch done";
+ callNames.clear();
+ callNames << QStringLiteral("itemsRetrieved") << QStringLiteral("applyCollectionChanges") << QStringLiteral("itemsRetrievalDone");
+
+@@ -596,7 +593,7 @@ private Q_SLOTS:
+ task->start(&pool);
+
+ QTRY_COMPARE(state->calls().count(), callNames.size());
+- qDebug() << state->calls();
++ // qDebug() << state->calls();
+ for (int i = 0; i < callNames.size(); i++) {
+ QString command = QString::fromUtf8(state->calls().at(i).first);
+ QVariant parameter = state->calls().at(i).second;
+diff --git a/resources/imap/retrieveitemstask.cpp b/resources/imap/retrieveitemstask.cpp
+index ee43142f80d5296954bc01f56d037d3b3c1e29b2..b3751e1b5c5b1b57fa293a38b93622f3d43877e8 100644
+--- a/resources/imap/retrieveitemstask.cpp
++++ b/resources/imap/retrieveitemstask.cpp
+@@ -357,11 +357,11 @@ void RetrieveItemsTask::prepareRetrieval()
+ scope.mode = KIMAP::FetchJob::FetchScope::Full;
+ }
+
+- const qint64 realMessageCount = col.statistics().count();
++ m_localMessageCount = col.statistics().count();
+
+ qCDebug(IMAPRESOURCE_LOG) << "Starting message retrieval. Elapsed(ms): " << m_time.elapsed();
+ qCDebug(IMAPRESOURCE_LOG) << "UidValidity: " << m_uidValidity << "Local UidValidity: " << oldUidValidity;
+- qCDebug(IMAPRESOURCE_LOG) << "MessageCount: " << m_messageCount << "Local message count: " << realMessageCount;
++ qCDebug(IMAPRESOURCE_LOG) << "MessageCount: " << m_messageCount << "Local message count: " << m_localMessageCount;
+ qCDebug(IMAPRESOURCE_LOG) << "UidNext: " << m_nextUid << "Local UidNext: " << oldNextUid;
+ qCDebug(IMAPRESOURCE_LOG) << "HighestModSeq: " << m_highestModSeq << "Local HighestModSeq: " << oldHighestModSeq;
+
+@@ -384,7 +384,7 @@ void RetrieveItemsTask::prepareRetrieval()
+ // Shortcut:
+ // If no messages are present on the server, clear local cash and finish
+ m_incremental = false;
+- if (realMessageCount > 0) {
++ if (m_localMessageCount > 0) {
+ qCDebug(IMAPRESOURCE_LOG) << "No messages present so we are done, deleting local messages.";
+ itemsRetrieved(Akonadi::Item::List());
+ } else {
+@@ -401,15 +401,15 @@ void RetrieveItemsTask::prepareRetrieval()
+ }
+ qCDebug(IMAPRESOURCE_LOG) << "Fetching complete mailbox " << m_mailBox;
+ setTotalItems(m_messageCount);
+- retrieveItems(KIMAP::ImapSet(1, m_nextUid), scope, false, true);
++ retrieveItems(KIMAP::ImapSet(1, m_messageCount), scope, false, false);
+ } else if (m_nextUid <= 0) {
+ // This is a compatibility codepath for Courier IMAP. It probably introduces problems, but at least it syncs.
+ // Since we don't have uidnext available, we simply use the messagecount. This will miss simultaneously added/removed messages.
+ // qCDebug(IMAPRESOURCE_LOG) << "Running courier imap compatibility codepath";
+- if (m_messageCount > realMessageCount) {
++ if (m_messageCount > m_localMessageCount) {
+ // Get new messages
+- retrieveItems(KIMAP::ImapSet(realMessageCount + 1, m_messageCount), scope, false, false);
+- } else if (m_messageCount == realMessageCount) {
++ retrieveItems(KIMAP::ImapSet(m_localMessageCount + 1, m_messageCount), scope, false, false);
++ } else if (m_messageCount == m_localMessageCount) {
+ m_uidBasedFetch = false;
+ m_incremental = true;
+ setTotalItems(m_messageCount);
+@@ -427,23 +427,23 @@ void RetrieveItemsTask::prepareRetrieval()
+ KIMAP::ImapSet imapSet;
+ imapSet.add(m_messageUidsMissingBody);
+ retrieveItems(imapSet, scope, true, true);
+- } else if (m_nextUid > oldNextUid && ((realMessageCount + m_nextUid - oldNextUid) == m_messageCount) && realMessageCount > 0) {
++ } else if (m_nextUid > oldNextUid && ((m_localMessageCount + m_nextUid - oldNextUid) == m_messageCount) && m_localMessageCount > 0) {
+ // Optimization:
+ // New messages are available, but we know no messages have been removed.
+ // Fetch new messages, and then check for changed flags and removed messages
+ // We can make an incremental update and use modseq.
+ qCDebug(IMAPRESOURCE_LOG) << "Incrementally fetching new messages: UidNext: " << m_nextUid << " Old UidNext: " << oldNextUid << " message count "
+- << m_messageCount << realMessageCount;
+- setTotalItems(qMax(1ll, m_messageCount - realMessageCount));
++ << m_messageCount << m_localMessageCount;
++ setTotalItems(qMax(1ll, m_messageCount - m_localMessageCount));
+ m_flagsChanged = !(m_highestModSeq == oldHighestModSeq);
+ retrieveItems(KIMAP::ImapSet(qMax(1, oldNextUid), m_nextUid), scope, true, true);
+- } else if (m_nextUid > oldNextUid && m_messageCount > (realMessageCount + m_nextUid - oldNextUid) && realMessageCount > 0) {
++ } else if (m_nextUid > oldNextUid && m_messageCount > (m_localMessageCount + m_nextUid - oldNextUid) && m_localMessageCount > 0) {
+ // Error recovery:
+ // New messages are available, but not enough to justify the difference between the local and remote message count.
+ // This can be triggered if we i.e. clear the local cache, but the keep the annotations.
+ // If we didn't catch this case, we end up inserting flags only for every missing message.
+ qCWarning(IMAPRESOURCE_LOG) << m_mailBox << ": detected inconsistency in local cache, we're missing some messages. Server: " << m_messageCount
+- << " Local: " << realMessageCount;
++ << " Local: " << m_localMessageCount;
+ qCWarning(IMAPRESOURCE_LOG) << m_mailBox << ": refetching complete mailbox";
+ setTotalItems(m_messageCount);
+ retrieveItems(KIMAP::ImapSet(1, m_nextUid), scope, false, true);
+@@ -452,7 +452,7 @@ void RetrieveItemsTask::prepareRetrieval()
+ qCDebug(IMAPRESOURCE_LOG) << "Fetching new messages: UidNext: " << m_nextUid << " Old UidNext: " << oldNextUid;
+ setTotalItems(m_messageCount);
+ retrieveItems(KIMAP::ImapSet(qMax(1, oldNextUid), m_nextUid), scope, false, true);
+- } else if (m_messageCount == realMessageCount && oldNextUid == m_nextUid) {
++ } else if (m_messageCount == m_localMessageCount && oldNextUid == m_nextUid) {
+ // Optimization:
+ // We know no messages were added or removed (if the message count and uidnext is still the same)
+ // We only check the flags incrementally and can make use of modseq
+@@ -469,22 +469,24 @@ void RetrieveItemsTask::prepareRetrieval()
+ }
+ setTotalItems(m_messageCount);
+ listFlagsForImapSet(KIMAP::ImapSet(1, m_nextUid));
+- } else if (m_messageCount > realMessageCount) {
++ } else if (m_messageCount > m_localMessageCount) {
+ // Error recovery:
+ // We didn't detect any new messages based on the uid, but according to the message count there are new ones.
+ // Our local cache is invalid and has to be refetched.
+ qCWarning(IMAPRESOURCE_LOG) << m_mailBox << ": detected inconsistency in local cache, we're missing some messages. Server: " << m_messageCount
+- << " Local: " << realMessageCount;
++ << " Local: " << m_localMessageCount;
+ qCWarning(IMAPRESOURCE_LOG) << m_mailBox << ": refetching complete mailbox";
+ setTotalItems(m_messageCount);
+ retrieveItems(KIMAP::ImapSet(1, m_nextUid), scope, false, true);
+ } else {
+ // Shortcut:
+ // No new messages are available. Directly check for changed flags and removed messages.
+- m_uidBasedFetch = true;
++ // Since we are checking all messages anyway, don't use UID FETCH to avoid searching for UIDs,
++ // we can do batching based on sequence numbers.
++ m_uidBasedFetch = false;
+ m_incremental = false;
+ setTotalItems(m_messageCount);
+- listFlagsForImapSet(KIMAP::ImapSet(1, m_nextUid));
++ listFlagsForImapSet(KIMAP::ImapSet(1, m_messageCount));
+ }
+ }
+
+@@ -553,9 +555,13 @@ void RetrieveItemsTask::onRetrievalDone(KJob *job)
+ return;
+ }
+
+- // Fetch flags of all items that were not fetched by the fetchJob. After
+- // that /all/ items in the folder are synced.
+- listFlagsForImapSet(KIMAP::ImapSet(1, alreadyFetchedBegin - 1));
++ // Fetch flags of all items that were not fetched by the fetchJob. The always fetches
++ // only new messages, so what remains are all messages that are cached locally.
++ // To avoid expensive UID SEARCH, we disable UID based fetching and just batch the flags
++ // fetch based on sequence numbers.
++ // After that /all/ items in the folder are synced.
++ m_uidBasedFetch = false;
++ listFlagsForImapSet(KIMAP::ImapSet(1, m_localMessageCount));
+ }
+
+ void RetrieveItemsTask::listFlagsForImapSet(const KIMAP::ImapSet &set)
+diff --git a/resources/imap/retrieveitemstask.h b/resources/imap/retrieveitemstask.h
+index 263347700cf16571f8a6e82ec74d9c6c15faf86e..984987a1f82b17d5ae66633d949b1a268fa3ad31 100644
+--- a/resources/imap/retrieveitemstask.h
++++ b/resources/imap/retrieveitemstask.h
+@@ -66,6 +66,7 @@ private:
+ bool m_fetchMissingBodies = false;
+ bool m_incremental = true;
+ qint64 m_localHighestModSeq = -1;
++ qint64 m_localMessageCount = -1;
+ BatchFetcher *m_batchFetcher = nullptr;
+ Akonadi::Collection m_modifiedCollection;
+ bool m_uidBasedFetch = true;
\ No newline at end of file
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..4f32b20
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1 @@
+imap_avoid_doing_search.diff
\ No newline at end of file
More information about the Neon-commits
mailing list