[prev in list] [next in list] [prev in thread] [next in thread] 

List:       mutt-dev
Subject:    mutt: Make cmd_parse_fetch() more precise about setting reopen/c...
From:       Brendan Cully <brendan () kublai ! com>
Date:       2017-09-27 20:50:19
Message-ID: hg.e98ad5446640.1506545419.1928362535899276112 () dev ! cs ! ubc ! ca
[Download RAW message or body]

changeset: 7170:e98ad5446640
user:      Kevin McCarthy <kevin@8t8.us>
date:      Wed Sep 27 13:45:36 2017 -0700
link:      http://dev.mutt.org/hg/mutt/rev/e98ad5446640

Make cmd_parse_fetch() more precise about setting reopen/check flags.

Previously any FETCH with FLAGS would result in either
  idata->reopen |= IMAP_EXPUNGE_PENDING;
  -or-
  idata->check_status = IMAP_FLAGS_PENDING;
being set.

This is unnecessary in the case of responses to FLAGS.SILENT updates
sent by mutt (which seem to commonly happen now-a-days).

Change imap_set_flags() to compare the old server flags against the
new ones, and report when _those_ updates would/did result in a local
header flag change.  Only set one of the reopen/check_status flags in
the event of an actual change (or potential change if a local change
has been made to the header.)

diffs (146 lines):

diff -r cbe207b97a2a -r e98ad5446640 imap/command.c
--- a/imap/command.c	Tue Sep 26 19:45:23 2017 -0700
+++ b/imap/command.c	Wed Sep 27 13:45:36 2017 -0700
@@ -652,6 +652,7 @@
 {
   unsigned int msn, uid;
   HEADER *h;
+  int server_changes = 0;
 
   dprint (3, (debugfile, "Handling FETCH\n"));
 
@@ -687,13 +688,14 @@
 
     if (ascii_strncasecmp ("FLAGS", s, 5) == 0)
     {
-      /* If server flags could conflict with mutt's flags, reopen the mailbox. */
-      if (h->changed)
-        idata->reopen |= IMAP_EXPUNGE_PENDING;
-      else
+      imap_set_flags (idata, h, s, &server_changes);
+      if (server_changes)
       {
-        imap_set_flags (idata, h, s);
-        idata->check_status = IMAP_FLAGS_PENDING;
+        /* If server flags could conflict with mutt's flags, reopen the mailbox. */
+        if (h->changed)
+          idata->reopen |= IMAP_EXPUNGE_PENDING;
+        else
+          idata->check_status = IMAP_FLAGS_PENDING;
       }
       return;
     }
diff -r cbe207b97a2a -r e98ad5446640 imap/imap_private.h
--- a/imap/imap_private.h	Tue Sep 26 19:45:23 2017 -0700
+++ b/imap/imap_private.h	Wed Sep 27 13:45:36 2017 -0700
@@ -269,7 +269,7 @@
 void imap_add_keywords (char* s, HEADER* keywords, LIST* mailbox_flags, size_t slen);
 void imap_free_header_data (IMAP_HEADER_DATA** data);
 int imap_read_headers (IMAP_DATA* idata, unsigned int msn_begin, unsigned int msn_end);
-char* imap_set_flags (IMAP_DATA* idata, HEADER* h, char* s);
+char* imap_set_flags (IMAP_DATA* idata, HEADER* h, char* s, int *server_changes);
 int imap_cache_del (IMAP_DATA* idata, HEADER* h);
 int imap_cache_clean (IMAP_DATA* idata);
 
diff -r cbe207b97a2a -r e98ad5446640 imap/message.c
--- a/imap/message.c	Tue Sep 26 19:45:23 2017 -0700
+++ b/imap/message.c	Wed Sep 27 13:45:36 2017 -0700
@@ -652,7 +652,7 @@
 	 * incrementally update flags later, this won't stop us syncing */
 	else if ((ascii_strncasecmp ("FLAGS", pc, 5) == 0) && !h->changed)
 	{
-	  if ((pc = imap_set_flags (idata, h, pc)) == NULL)
+	  if ((pc = imap_set_flags (idata, h, pc, NULL)) == NULL)
 	    goto bail;
 	}
       }
@@ -1183,19 +1183,55 @@
   }
 }
 
+/* Sets server_changes to 1 if a change to a flag is made, or in the
+ * case of local_changes, if a change to a flag _would_ have been
+ * made. */
+static void imap_set_changed_flag (CONTEXT *ctx, HEADER *h, int local_changes,
+                                   int *server_changes, int flag_name, int old_hd_flag,
+                                   int new_hd_flag, int h_flag)
+{
+  /* If there are local_changes, we only want to note if the server
+   * flags have changed, so we can set a reopen flag in
+   * cmd_parse_fetch().  We don't want to count a local modification
+   * to the header flag as a "change".
+   */
+  if ((old_hd_flag != new_hd_flag) || (!local_changes))
+  {
+    if (new_hd_flag != h_flag)
+    {
+      if (server_changes)
+        *server_changes = 1;
+
+      /* Local changes have priority */
+      if (!local_changes)
+        mutt_set_flag (ctx, h, flag_name, new_hd_flag);
+    }
+  }
+}
+
 /* imap_set_flags: fill out the message header according to the flags from
- *   the server. Expects a flags line of the form "FLAGS (flag flag ...)" */
-char* imap_set_flags (IMAP_DATA* idata, HEADER* h, char* s)
+ * the server. Expects a flags line of the form "FLAGS (flag flag ...)"
+ *
+ * Sets server_changes to 1 if a change to a flag is made, or in the
+ * case of h->changed, if a change to a flag _would_ have been
+ * made. */
+char* imap_set_flags (IMAP_DATA* idata, HEADER* h, char* s, int *server_changes)
 {
   CONTEXT* ctx = idata->ctx;
   IMAP_HEADER newh;
+  IMAP_HEADER_DATA old_hd;
   IMAP_HEADER_DATA* hd;
   unsigned char readonly;
+  int local_changes;
+
+  local_changes = h->changed;
 
   memset (&newh, 0, sizeof (newh));
   hd = h->data;
   newh.data = hd;
 
+  memcpy (&old_hd, hd, sizeof(old_hd));
+
   dprint (2, (debugfile, "imap_set_flags: parsing FLAGS\n"));
   if ((s = msg_parse_flags (&newh, s)) == NULL)
     return NULL;
@@ -1207,16 +1243,24 @@
   readonly = ctx->readonly;
   ctx->readonly = 0;
 
-  mutt_set_flag (ctx, h, MUTT_NEW, !(hd->read || hd->old));
-  mutt_set_flag (ctx, h, MUTT_OLD, hd->old);
-  mutt_set_flag (ctx, h, MUTT_READ, hd->read);
-  mutt_set_flag (ctx, h, MUTT_DELETE, hd->deleted);
-  mutt_set_flag (ctx, h, MUTT_FLAG, hd->flagged);
-  mutt_set_flag (ctx, h, MUTT_REPLIED, hd->replied);
+  /* This is redundant with the following two checks. Removing:
+   * mutt_set_flag (ctx, h, MUTT_NEW, !(hd->read || hd->old));
+   */
+  imap_set_changed_flag (ctx, h, local_changes, server_changes,
+                         MUTT_OLD, old_hd.old, hd->old, h->old);
+  imap_set_changed_flag (ctx, h, local_changes, server_changes,
+                         MUTT_READ, old_hd.read, hd->read, h->read);
+  imap_set_changed_flag (ctx, h, local_changes, server_changes,
+                         MUTT_DELETE, old_hd.deleted, hd->deleted, h->deleted);
+  imap_set_changed_flag (ctx, h, local_changes, server_changes,
+                         MUTT_FLAG, old_hd.flagged, hd->flagged, h->flagged);
+  imap_set_changed_flag (ctx, h, local_changes, server_changes,
+                         MUTT_REPLIED, old_hd.replied, hd->replied, h->replied);
 
   /* this message is now definitively *not* changed (mutt_set_flag
    * marks things changed as a side-effect) */
-  h->changed = 0;
+  if (!local_changes)
+    h->changed = 0;
   ctx->changed &= ~readonly;
   ctx->readonly = readonly;
 
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic