]> granicus.if.org Git - mutt/commitdiff
Cache server-side flags, don't send flag updates if mutt's are the same.
authorBrendan Cully <brendan@kublai.com>
Mon, 19 Dec 2005 17:31:03 +0000 (17:31 +0000)
committerBrendan Cully <brendan@kublai.com>
Mon, 19 Dec 2005 17:31:03 +0000 (17:31 +0000)
This can happen if a flag is toggled and toggled back, or we receive
server updates, and the cache will make much faster sync possible later.

imap/imap.c
imap/message.c
imap/message.h

index 013956f25f2d6136bb4c16a0a99063885d1a92eb..a508b2da10a13097fec49b3f8b7926f91fb490fe 100644 (file)
@@ -896,6 +896,25 @@ int imap_make_msg_set (IMAP_DATA* idata, BUFFER* buf, int flag, int changed)
   return count;
 }
 
+/* returns 0 if mutt's flags match cached server flags */
+static int compare_flags (HEADER* h)
+{
+  IMAP_HEADER_DATA* hd = (IMAP_HEADER_DATA*)h->data;
+
+  if (h->read != hd->read)
+    return 1;
+  if (h->old != hd->old)
+    return 1;
+  if (h->flagged != hd->flagged)
+    return 1;
+  if (h->replied != hd->replied)
+    return 1;
+  if (h->deleted != hd->deleted)
+    return 1;
+
+  return 0;
+}
+
 /* Update the IMAP server to reflect the flags a single message.  */
 
 int imap_sync_message (IMAP_DATA *idata, HEADER *hdr, BUFFER *cmd,
@@ -906,6 +925,12 @@ int imap_sync_message (IMAP_DATA *idata, HEADER *hdr, BUFFER *cmd,
 
   hdr->changed = 0;
 
+  if (!compare_flags (hdr))
+  {
+    idata->ctx->changed--;
+    return 0;
+  }
+
   snprintf (uid, sizeof (uid), "%u", HEADER_DATA(hdr)->uid);
   cmd->dptr = cmd->data;
   mutt_buffer_addstr (cmd, "UID STORE ");
@@ -974,7 +999,6 @@ int imap_sync_message (IMAP_DATA *idata, HEADER *hdr, BUFFER *cmd,
  *   ctx: the current context
  *   expunge: 0 or 1 - do expunge? 
  */
-
 int imap_sync_mailbox (CONTEXT* ctx, int expunge, int* index_hint)
 {
   IMAP_DATA* idata;
@@ -1033,6 +1057,12 @@ int imap_sync_mailbox (CONTEXT* ctx, int expunge, int* index_hint)
   {
     if (ctx->hdrs[n]->active && ctx->hdrs[n]->changed)
     {
+      if (!compare_flags (ctx->hdrs[n]))
+      {
+        /* current flags are no different from server's idea */
+        ctx->hdrs[n]->changed = 0;
+        continue;
+      }
       mutt_message (_("Saving message status flags... [%d/%d]"), n+1,
         ctx->msgcount);
 
index 5169ca2f18317257cf28f25450b3f4337913ba70..dc51294511c866133953a7db54248dae0b274d4b 100644 (file)
@@ -156,12 +156,12 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend)
          /* messages which have not been expunged are ACTIVE (borrowed from mh 
           * folders) */
          ctx->hdrs[msgno]->active = 1;
-         ctx->hdrs[msgno]->read = h.read;
-          ctx->hdrs[msgno]->old = h.old;
-          ctx->hdrs[msgno]->deleted = h.deleted;
-          ctx->hdrs[msgno]->flagged = h.flagged;
-          ctx->hdrs[msgno]->replied = h.replied;
-          ctx->hdrs[msgno]->changed = h.changed;
+          ctx->hdrs[msgno]->read = h.data->read;
+          ctx->hdrs[msgno]->old = h.data->old;
+          ctx->hdrs[msgno]->deleted = h.data->deleted;
+          ctx->hdrs[msgno]->flagged = h.data->flagged;
+          ctx->hdrs[msgno]->replied = h.data->replied;
+          ctx->hdrs[msgno]->changed = h.data->changed;
           /*  ctx->hdrs[msgno]->received is restored from mutt_hcache_restore */
           ctx->hdrs[msgno]->data = (void *) (h.data);
 
@@ -249,12 +249,12 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend)
       /* messages which have not been expunged are ACTIVE (borrowed from mh 
        * folders) */
       ctx->hdrs[msgno]->active = 1;
-      ctx->hdrs[msgno]->read = h.read;
-      ctx->hdrs[msgno]->old = h.old;
-      ctx->hdrs[msgno]->deleted = h.deleted;
-      ctx->hdrs[msgno]->flagged = h.flagged;
-      ctx->hdrs[msgno]->replied = h.replied;
-      ctx->hdrs[msgno]->changed = h.changed;
+      ctx->hdrs[msgno]->read = h.data->read;
+      ctx->hdrs[msgno]->old = h.data->old;
+      ctx->hdrs[msgno]->deleted = h.data->deleted;
+      ctx->hdrs[msgno]->flagged = h.data->flagged;
+      ctx->hdrs[msgno]->replied = h.data->replied;
+      ctx->hdrs[msgno]->changed = h.data->changed;
       ctx->hdrs[msgno]->received = h.received;
       ctx->hdrs[msgno]->data = (void *) (h.data);
 
@@ -834,17 +834,16 @@ char* imap_set_flags (IMAP_DATA* idata, HEADER* h, char* s)
 {
   CONTEXT* ctx = idata->ctx;
   IMAP_HEADER newh;
+  IMAP_HEADER_DATA* hd;
   unsigned char readonly;
 
   memset (&newh, 0, sizeof (newh));
-  newh.data = safe_calloc (1, sizeof (IMAP_HEADER_DATA));
+  hd = h->data;
+  newh.data = hd;
 
   dprint (2, (debugfile, "imap_fetch_message: parsing FLAGS\n"));
   if ((s = msg_parse_flags (&newh, s)) == NULL)
-  {
-    FREE (&newh.data);
     return NULL;
-  }
   
   /* YAUH (yet another ugly hack): temporarily set context to
    * read-write even if it's read-only, so *server* updates of
@@ -853,12 +852,12 @@ char* imap_set_flags (IMAP_DATA* idata, HEADER* h, char* s)
   readonly = ctx->readonly;
   ctx->readonly = 0;
            
-  mutt_set_flag (ctx, h, M_NEW, !(newh.read || newh.old));
-  mutt_set_flag (ctx, h, M_OLD, newh.old);
-  mutt_set_flag (ctx, h, M_READ, newh.read);
-  mutt_set_flag (ctx, h, M_DELETE, newh.deleted);
-  mutt_set_flag (ctx, h, M_FLAG, newh.flagged);
-  mutt_set_flag (ctx, h, M_REPLIED, newh.replied);
+  mutt_set_flag (ctx, h, M_NEW, !(hd->read || hd->old));
+  mutt_set_flag (ctx, h, M_OLD, hd->old);
+  mutt_set_flag (ctx, h, M_READ, hd->read);
+  mutt_set_flag (ctx, h, M_DELETE, hd->deleted);
+  mutt_set_flag (ctx, h, M_FLAG, hd->flagged);
+  mutt_set_flag (ctx, h, M_REPLIED, hd->replied);
 
   /* this message is now definitively *not* changed (mutt_set_flag
    * marks things changed as a side-effect) */
@@ -866,10 +865,6 @@ char* imap_set_flags (IMAP_DATA* idata, HEADER* h, char* s)
   ctx->changed &= ~readonly;
   ctx->readonly = readonly;
 
-  mutt_free_list (&(HEADER_DATA(h)->keywords));
-  HEADER_DATA(h)->keywords = newh.data->keywords;
-  FREE(&newh.data);
-
   return s;
 }
 
@@ -1018,7 +1013,7 @@ static int msg_parse_fetch (IMAP_HEADER *h, char *s)
 /* msg_parse_flags: read a FLAGS token into an IMAP_HEADER */
 static char* msg_parse_flags (IMAP_HEADER* h, char* s)
 {
-  int recent = 0;
+  IMAP_HEADER_DATA* hd = h->data;
 
   /* sanity-check string */
   if (ascii_strncasecmp ("FLAGS", s, 5) != 0)
@@ -1037,38 +1032,38 @@ static char* msg_parse_flags (IMAP_HEADER* h, char* s)
   }
   s++;
 
+  mutt_free_list (&hd->keywords);
+  hd->deleted = hd->flagged = hd->replied = hd->read = hd->old = 0;
+
   /* start parsing */
   while (*s && *s != ')')
   {
     if (ascii_strncasecmp ("\\deleted", s, 8) == 0)
     {
       s += 8;
-      h->deleted = 1;
+      hd->deleted = 1;
     }
     else if (ascii_strncasecmp ("\\flagged", s, 8) == 0)
     {
       s += 8;
-      h->flagged = 1;
+      hd->flagged = 1;
     }
     else if (ascii_strncasecmp ("\\answered", s, 9) == 0)
     {
       s += 9;
-      h->replied = 1;
+      hd->replied = 1;
     }
     else if (ascii_strncasecmp ("\\seen", s, 5) == 0)
     {
       s += 5;
-      h->read = 1;
+      hd->read = 1;
     }
     else if (ascii_strncasecmp ("\\recent", s, 5) == 0)
-    {
       s += 7;
-      recent = 1;
-    }
     else if (ascii_strncasecmp ("old", s, 3) == 0)
     {
       s += 3;
-      h->old = 1;
+      hd->old = 1;
     }
     else
     {
@@ -1076,14 +1071,14 @@ static char* msg_parse_flags (IMAP_HEADER* h, char* s)
       char ctmp;
       char* flag_word = s;
 
-      if (!h->data->keywords)
-        h->data->keywords = mutt_new_list ();
+      if (!hd->keywords)
+        hd->keywords = mutt_new_list ();
 
       while (*s && !ISSPACE (*s) && *s != ')')
         s++;
       ctmp = *s;
       *s = '\0';
-      mutt_add_list (h->data->keywords, flag_word);
+      mutt_add_list (hd->keywords, flag_word);
       *s = ctmp;
     }
     SKIPWS(s);
@@ -1091,9 +1086,7 @@ static char* msg_parse_flags (IMAP_HEADER* h, char* s)
 
   /* wrap up, or note bad flags response */
   if (*s == ')')
-  {
     s++;
-  }
   else
   {
     dprint (1, (debugfile,
index 68478a9c31c43b65531c301d9dc02afd605325ef..fc763848ceb599f53c14f3a341c0c88572d1fddd 100644 (file)
 /* IMAP-specific header data, stored as HEADER->data */
 typedef struct imap_header_data
 {
-  unsigned int uid;    /* 32-bit Message UID */
-  LIST *keywords;
-} IMAP_HEADER_DATA;
-
-typedef struct
-{
+  /* server-side flags */
   unsigned int read : 1;
   unsigned int old : 1;
   unsigned int deleted : 1;
@@ -39,6 +34,12 @@ typedef struct
   unsigned int replied : 1;
   unsigned int changed : 1;
 
+  unsigned int uid;    /* 32-bit Message UID */
+  LIST *keywords;
+} IMAP_HEADER_DATA;
+
+typedef struct
+{
   unsigned int sid;
 
   IMAP_HEADER_DATA* data;