commit eab3874918f9c80db69a1b72d2f546efba4caa01
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Wed Jun 1 14:04:12 2022 +0200

    orphan/prune sync entries also if messages were expunged externally
    
    deletions we propagated ourselves are implicitly covered by that as
    well, so we don't need to record them separately anymore.

 src/run-tests.pl | 24 ++++++++++++++++++++++++
 src/sync.c       | 44 ++++++++++++++++++++++----------------------
 src/sync_p.h     |  1 +
 3 files changed, 47 insertions(+), 22 deletions(-)

diff --git a/src/run-tests.pl b/src/run-tests.pl
index 6a126168..64c926ad 100755
--- a/src/run-tests.pl
+++ b/src/run-tests.pl
@@ -941,6 +941,7 @@ sub test($$$$)
 
 my @x01 = (
   I, 0, I,
+  P, "_", "*", "_",
   R, "*", "", "",  # Skipped/failed messages to prevent maxuid topping
   S, "", "", "*",
   A, "*F", "*", "*",
@@ -949,6 +950,8 @@ my @x01 = (
   D, "*", "*", "*",
   E, "*T", "*", "*",
   F, "*", "*", "*T",
+  O, "*T", "*T", "*T",
+  Q, "_", "*T", "*T",
   G, "*F", "*", "_",
   H, "*FT", "*", "*",
   I, "_", "*", "*",
@@ -961,11 +964,13 @@ my @x01 = (
 my @O01 = ("", "", "");
 my @X01 = (
   M, 0, K,
+  P, "", "/", "",
   A, "", "+F", "+F",
   B, "+F", "+F", "",
   C, "", "+FS", "+S",
   E, "", "+T", "+T",
   F, "+T", "+T", "",
+  Q, "", "<", "",
   G, "+T", ">", "",
   H, "", "+FT", "+FT",
   I, "", "<", "+T",
@@ -979,11 +984,14 @@ test("full", \@x01, \@X01, \@O01);
 my @O02 = ("", "", "Expunge Both\n");
 my @X02 = (
   M, 0, K,
+  P, "", "/", "",
   A, "", "+F", "+F",
   B, "+F", "+F", "",
   C, "", "+FS", "+S",
   E, "/", "/", "/",
   F, "/", "/", "/",
+  O, "/", "/", "/",
+  Q, "", "/", "/",
   G, "/", "/", "",
   H, "/", "/", "/",
   I, "", "/", "/",
@@ -997,11 +1005,14 @@ test("full + expunge both", \@x01, \@X02, \@O02);
 my @O03 = ("", "", "Expunge Near\n");
 my @X03 = (
   M, 0, K,
+  P, "", "/", "",
   A, "", "+F", "+F",
   B, "+F", "+F", "",
   C, "", "+FS", "+S",
   E, "", ">+T", "/",
   F, "+T", ">+T", "/",
+  O, "", ">", "/",
+  Q, "", "/", "/",
   G, "+T", ">", "",
   H, "", ">+T", "/",
   I, "", "/", "/",
@@ -1014,9 +1025,11 @@ test("full + expunge near side", \@x01, \@X03, \@O03);
 my @O04 = ("", "", "Sync Pull\n");
 my @X04 = (
   K, 0, I,
+  P, "", "/", "",  # Only because test uses Maildir driver
   A, "", "+F", "+F",
   C, "", "+FS", "+S",
   E, "", "+T", "+T",
+  Q, "", "<", "",
   H, "", "+FT", "+FT",
   I, "", "<", "+T",
   J, "", "*T", "*T",
@@ -1027,11 +1040,13 @@ test("pull", \@x01, \@X04, \@O04);
 my @O05 = ("", "", "Sync Flags\n");
 my @X05 = (
   I, 0, I,
+  P, "", "/", "",
   A, "", "+F", "+F",
   B, "+F", "+F", "",
   C, "", "+FS", "+S",
   E, "", "+T", "+T",
   F, "+T", "+T", "",
+  Q, "", "<", "",
   H, "", "+FT", "+FT",
 );
 test("flags", \@x01, \@X05, \@O05);
@@ -1039,7 +1054,9 @@ test("flags", \@x01, \@X05, \@O05);
 my @O06 = ("", "", "Sync Delete\n");
 my @X06 = (
   I, 0, I,
+  P, "", "/", "",
   G, "+T", ">", "",
+  Q, "", "<", "",
   I, "", "<", "+T",
 );
 test("deletions", \@x01, \@X06, \@O06);
@@ -1057,9 +1074,11 @@ test("new", \@x01, \@X07, \@O07);
 my @O08 = ("", "", "Sync PushFlags PullDelete\n");
 my @X08 = (
   I, 0, I,
+  P, "", "/", "",
   B, "+F", "+F", "",
   C, "", "+F", "",
   F, "+T", "+T", "",
+  Q, "", "<", "",
   I, "", "<", "+T",
 );
 test("push flags + pull deletions", \@x01, \@X08, \@O08);
@@ -1067,8 +1086,11 @@ test("push flags + pull deletions", \@x01, \@X08, \@O08);
 my @O09 = ("", "", "Sync None\nExpunge Both\n");
 my @X09 = (
   I, 0, I,
+  P, "", "/", "",
   E, "/", "", "",
   F, "", "", "/",
+  O, "/", "/", "/",
+  Q, "", "/", "/",
   H, "/", "", "",
   J, "/", "", "",
   L, "", "", "/",
@@ -1080,6 +1102,8 @@ my @O0A = ("", "", "Sync None\nExpunge Near\n");
 my @X0A = (
   I, 0, I,
   F, "", "", "/",
+  O, "", "", "/",
+  Q, "", "", "/",
   L, "", "", "/",
 );
 test("noop + expunge near side", \@x01, \@X0A, \@O0A);
diff --git a/src/sync.c b/src/sync.c
index a2d4746b..e52eed0e 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -1036,6 +1036,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
                                } else if (del[t]) {
                                        // The target was newly expunged, so 
there is nothing to update.
                                        // The deletion is propagated in the 
opposite iteration.
+                                       srec->status |= S_GONE(t);
                                } else if (!srec->uid[t]) {
                                        // The target was never stored, or was 
previously expunged, so there
                                        // is nothing to update.
@@ -1340,7 +1341,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int 
recent_msgs, void *aux
                for (t = 0; t < 2; t++) {
                        if (!srec->uid[t])
                                continue;
-                       if (!srec->msg[t] && (svars->opts[t] & OPEN_OLD)) {
+                       if (srec->status & S_GONE(t)) {
                                // The message was expunged. No need to call 
flags_set(), because:
                                // - for S_DELETE and S_PURGE, the entry will 
be pruned due to both sides being gone
                                // - for regular flag propagations, there is 
nothing to do
@@ -1571,10 +1572,7 @@ flags_set_p2( sync_vars_t *svars, sync_rec_t *srec, int 
t )
        if (srec->status & S_PURGE) {
                JLOG( "P %u %u", (srec->uid[F], srec->uid[N]), "deleted dummy" 
);
                srec->status = (srec->status & ~S_PURGE) | S_PURGED;
-       } else if (srec->status & S_DELETE) {
-               JLOG( "%c %u %u 0", ("><"[t], srec->uid[F], srec->uid[N]), 
"%sed deletion", str_hl[t] );
-               srec->uid[t^1] = 0;
-       } else {
+       } else if (!(srec->status & S_DELETE)) {
                uchar nflags = (srec->flags | srec->aflags[t]) & 
~srec->dflags[t];
                if (srec->flags != nflags) {
                        JLOG( "* %u %u %u", (srec->uid[F], srec->uid[N], 
nflags), "%sed flags %s; were %s",
@@ -1802,24 +1800,26 @@ box_closed_p2( sync_vars_t *svars, int t )
                        PC_JLOG( "N %d %u", (t, svars->maxuid[t]), "up maxuid 
of %s", str_fn[t] );
        }
 
-       if (((svars->state[F] | svars->state[N]) & ST_DID_EXPUNGE) || 
svars->chan->max_messages) {
-               debug( "purging obsolete entries\n" );
-               for (srec = svars->srecs; srec; srec = srec->next) {
-                       if (srec->status & S_DEAD)
-                               continue;
-                       if (!srec->uid[N] || ((srec->status & S_DEL(N)) && 
(svars->state[N] & ST_DID_EXPUNGE))) {
-                               if (!srec->uid[F] || ((srec->status & S_DEL(F)) 
&& (svars->state[F] & ST_DID_EXPUNGE)) ||
-                                   ((srec->status & S_EXPIRED) && 
svars->maxuid[F] >= srec->uid[F] && svars->maxxfuid >= srec->uid[F])) {
-                                       PC_JLOG( "- %u %u", (srec->uid[F], 
srec->uid[N]), "killing" );
-                                       srec->status = S_DEAD;
-                               } else if (srec->uid[N] && (srec->status & 
S_DEL(F))) {
-                                       PC_JLOG( "> %u %u 0", (srec->uid[F], 
srec->uid[N]), "orphaning" );
-                                       srec->uid[N] = 0;
-                               }
-                       } else if (srec->uid[F] && ((srec->status & S_DEL(F)) 
&& (svars->state[F] & ST_DID_EXPUNGE)) && (srec->status & S_DEL(N))) {
-                               PC_JLOG( "< %u %u 0", (srec->uid[F], 
srec->uid[N]), "orphaning" );
-                               srec->uid[F] = 0;
+       debug( "purging obsolete entries\n" );
+       for (srec = svars->srecs; srec; srec = srec->next) {
+               if (srec->status & S_DEAD)
+                       continue;
+               if ((srec->status & S_DEL(F)) && (svars->state[F] & 
ST_DID_EXPUNGE))
+                       srec->status |= S_GONE(F);
+               if ((srec->status & S_DEL(N)) && (svars->state[N] & 
ST_DID_EXPUNGE))
+                       srec->status |= S_GONE(N);
+               if (!srec->uid[N] || (srec->status & S_GONE(N))) {
+                       if (!srec->uid[F] || (srec->status & S_GONE(F)) ||
+                               ((srec->status & S_EXPIRED) && svars->maxuid[F] 
>= srec->uid[F] && svars->maxxfuid >= srec->uid[F])) {
+                               PC_JLOG( "- %u %u", (srec->uid[F], 
srec->uid[N]), "killing" );
+                               srec->status = S_DEAD;
+                       } else if (srec->uid[N] && (srec->status & S_DEL(F))) {
+                               PC_JLOG( "> %u %u 0", (srec->uid[F], 
srec->uid[N]), "orphaning" );
+                               srec->uid[N] = 0;
                        }
+               } else if (srec->uid[F] && (srec->status & S_GONE(F)) && 
(srec->status & S_DEL(N))) {
+                       PC_JLOG( "< %u %u 0", (srec->uid[F], srec->uid[N]), 
"orphaning" );
+                       srec->uid[F] = 0;
                }
        }
 
diff --git a/src/sync_p.h b/src/sync_p.h
index 9e79830d..45fcd3c6 100644
--- a/src/sync_p.h
+++ b/src/sync_p.h
@@ -17,6 +17,7 @@ BIT_ENUM(
        S_PENDING,      // the entry is new and awaits propagation (possibly a 
retry)
        S_DUMMY(2),     // f/n message is only a placeholder
        S_SKIPPED,      // pre-1.4 legacy: the entry was not propagated 
(message is too big)
+       S_GONE(2),      // ephemeral: f/n message has been expunged
        S_DEL(2),       // ephemeral: f/n message would be subject to expunge
        S_DELETE,       // ephemeral: flags propagation is a deletion
        S_UPGRADE,      // ephemeral: upgrading placeholder, do not apply 
MaxSize


_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to