commit 8f39d06015c7491c81f40a35703cfe78529b868f
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Tue Feb 22 16:42:22 2022 +0100

    fix mixing MaxMessages with MaxSize
    
    this is actually a useful combination for resource-constrained devices.

 NEWS             |   2 +
 src/run-tests.pl | 125 +++++++++++++++++++++++++++++++++++++++++++++++
 src/sync.c       |  28 +++++++++--
 3 files changed, 152 insertions(+), 3 deletions(-)

diff --git a/NEWS b/NEWS
index 4b1f260f..f7ce4512 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,8 @@ is now the file's containing directory.
 Placeholders will be now created for messages exceeding MaxSize even if
 they are flagged on the source side.
 
+MaxMessages and MaxSize can be used together now.
+
 The unfiltered list of mailboxes in each Store can be printed now.
 
 A proper summary is now printed prior to exiting.
diff --git a/src/run-tests.pl b/src/run-tests.pl
index 74cb0c5b..77d0ebc3 100755
--- a/src/run-tests.pl
+++ b/src/run-tests.pl
@@ -1313,6 +1313,131 @@ my @X38 = (
 );
 test("max messages + expunge", \@x38, \@X38, \@O38);
 
+# Expiration with size restriction tests
+
+my @x40 = (
+  P, 0, P,
+
+  A, "**", "*>", "*?",
+  B, "**", "*>", "*S?",
+  C, "**", "*>S", "*S?",
+  D, "*S*", "*>S", "*S?",
+  E, "*S*", "*>", "*S?",
+  F, "*S*", "*>S", "*?",
+  G, "*S*", "*>", "*?",
+  H, "**", "*>S", "*?",
+
+  I, "*F*", "*>", "*?",
+  J, "*F*", "*>", "*S?",
+  K, "*F*", "*>S", "*S?",
+  L, "*FS*", "*>S", "*S?",
+  M, "*FS*", "*>", "*S?",
+  N, "*FS*", "*>S", "*?",
+  O, "*FS*", "*>", "*?",
+  P, "*F*", "*>S", "*?",
+
+  Q, "**", "", "",
+  R, "*FS*", "", "",
+  S, "*S*", "", "",
+
+  T, "**", "", "",
+  U, "*FS*", "", "",
+  V, "*S*", "", "",
+);
+
+my @O41 = ("", "", "MaxSize 1k\nMaxMessages 3\nExpireUnread no\n");
+my @X41 = (
+  V, S, V,
+
+  C, "", "-S", "-S",
+  D, "", "+~", "+T",
+  E, "", "+~S", "+T",
+  F, "-S", "-S", "",
+  G, "", "+~S", "+ST",
+  H, "", "-S", "",
+
+  K, "", "-S", "-S",
+  M, "", "+S", "",
+  N, "-S", "-S", "",
+  O, "", "+S", "+S",
+  P, "", "-S", "",
+
+  Q, "", "*>", "*?",
+  R, "", "*>S", "*S?",
+
+  T, "", "*>", "*?",
+  U, "", "*>S", "*S?",
+  V, "", "*>S", "*S?",
+);
+test("max size without upgrade + max messages", \@x40, \@X41, \@O41);
+
+my @x42 = (
+  T, Q, T,
+
+  A, "**", "*>", "*F?",
+  B, "**", "*>", "*FS?",
+  C, "**", "*>S", "*FS?",
+  D, "*S*", "*>S", "*FS?",
+  E, "*S*", "*>", "*FS?",
+  F, "*S*", "*>S", "*F?",
+  G, "*S*", "*>", "*F?",
+  H, "**", "*>S", "*F?",
+
+  I, "*F*", "*>", "*F?",
+  J, "*F*", "*>", "*FS?",
+  K, "*F*", "*>S", "*FS?",
+  L, "*FS*", "*>S", "*FS?",
+  M, "*FS*", "*>", "*FS?",
+  N, "*FS*", "*>S", "*F?",
+  O, "*FS*", "*>", "*F?",
+  P, "*F*", "*>S", "*F?",
+
+  Q, "*S", "", "",
+
+  R, "*", "*", "*",
+  S, "*", "*", "*",
+  T, "*", "*", "*",
+);
+
+my @X43 = (
+  T, Q, P,
+
+  A, "", ">->", "^*",
+  A, "&", "^", "&1+T",
+  B, "", ">->", "^*",
+  B, "&", "^", "&1+T",
+  C, "", ">->S", "^*",
+  C, "&", "^", "&1+T",
+  D, "", "/", "",
+  D, "&", "^", "&1+T",
+  E, "", "/", "",
+  E, "&", "^", "&1+T",
+  F, "-S", ">->S", "^*",
+  F, "&", "^", "&1+T",
+  G, "", "/", "",
+  G, "&", "^", "&1+T",
+  H, "", ">->S", "^*",
+  H, "&", "^", "&1+T",
+
+  I, "", ">->+F", "^F*",
+  I, "&", "^", "&1+T",
+  J, "", ">->+F", "^F*",
+  J, "&", "^", "&1+T",
+  K, "", ">->S+F", "^F*",
+  K, "&", "^", "&1+T",
+  L, "", ">->+F", "^FS*",
+  L, "&", "^", "&1+T",
+  M, "", ">->+FS", "^FS*",
+  M, "&", "^", "&1+T",
+  N, "-S", ">->S+F", "^F*",
+  N, "&", "^", "&1+T",
+  O, "", ">->+FS", "^FS*",
+  O, "&", "^", "&1+T",
+  P, "", ">->S+F", "^F*",
+  P, "&", "^", "&1+T",
+);
+test("max size with upgrade + max messages", \@x42, \@X43, \@O41);
+
 # Test for legacy/tampered states with inaccurate maxuid tracking
 
 # Joined post-push & post-pull state to have just one test -
diff --git a/src/sync.c b/src/sync.c
index f476efbd..9a6233de 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -799,7 +799,9 @@ box_opened2( sync_vars_t *svars, int t )
                svars->any_expiring = 1;
        if (svars->any_expiring) {
                opts[N] |= OPEN_OLD | OPEN_FLAGS;
-               if (chan->ops[N] & (OP_NEW | OP_RENEW))
+               if (any_dummies[N])
+                       opts[F] |= OPEN_OLD | OPEN_FLAGS;
+               else if (chan->ops[N] & (OP_NEW | OP_RENEW))
                        opts[F] |= OPEN_FLAGS;
        }
        svars->opts[F] = svars->drv[F]->prepare_load_box( ctx[F], opts[F] );
@@ -1284,9 +1286,29 @@ box_loaded( int sts, message_t *msgs, int total_msgs, 
int recent_msgs, void *aux
                                // to expire in the first place.
                                if (!srec->msg[N])
                                        continue;
-                               nflags = (srec->msg[N]->flags | 
srec->aflags[N]) & ~srec->dflags[N];
+                               nflags = srec->msg[N]->flags;
+                               if (srec->status & S_DUMMY(N)) {
+                                       if (!srec->msg[F])
+                                               continue;
+                                       // We need to pull in the real Flagged 
and Seen even if flag
+                                       // propagation was not requested, as 
the placeholder's ones are
+                                       // useless (except for un-seeing).
+                                       // This results in the somewhat weird 
situation that messages
+                                       // which are not visibly flagged remain 
unexpired.
+                                       sflags = srec->msg[F]->flags;
+                                       aflags = (sflags & ~srec->flags) & 
(F_SEEN | F_FLAGGED);
+                                       dflags = (~sflags & srec->flags) & 
F_SEEN;
+                                       nflags = (nflags & (~(F_SEEN | 
F_FLAGGED) | (srec->flags & F_SEEN)) & ~dflags) | aflags;
+                               }
+                               nflags = (nflags | srec->aflags[N]) & 
~srec->dflags[N];
                        } else {
-                               nflags = srec->msg[F]->flags;
+                               if (srec->status & S_UPGRADE) {
+                                       // The dummy's F & S flags are mostly 
masked out anyway,
+                                       // but we may be pulling in the real 
ones.
+                                       nflags = (srec->pflags | 
srec->aflags[N]) & ~srec->dflags[N];
+                               } else {
+                                       nflags = srec->msg[F]->flags;
+                               }
                        }
                        if (!(nflags & F_DELETED) || (srec->status & (S_EXPIRE 
| S_EXPIRED))) {
                                // The message is not deleted, or it is, but 
only due to being expired.


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

Reply via email to