Browse Source

add ExpireUnread option

wip/maildir-uid-dupes-test
Oswald Buddenhagen 11 years ago
parent
commit
8d5bd62537
  1. 4
      src/config.c
  2. 1
      src/isync.h
  3. 14
      src/mbsync.1
  4. 12
      src/run-tests.pl
  5. 13
      src/sync.c

4
src/config.c

@ -233,6 +233,8 @@ getopt_helper( conffile_t *cfile, int *cops, channel_conf_t *conf )
conf->use_internal_date = parse_bool( cfile ); conf->use_internal_date = parse_bool( cfile );
else if (!strcasecmp( "MaxMessages", cfile->cmd )) else if (!strcasecmp( "MaxMessages", cfile->cmd ))
conf->max_messages = parse_int( cfile ); conf->max_messages = parse_int( cfile );
else if (!strcasecmp( "ExpireUnread", cfile->cmd ))
conf->expire_unread = parse_bool( cfile );
else else
return 0; return 0;
return 1; return 1;
@ -347,6 +349,7 @@ load_config( const char *where, int pseudo )
cfile.err = 0; cfile.err = 0;
gcops = 0; gcops = 0;
global_conf.expire_unread = -1;
reloop: reloop:
while (getcline( &cfile )) { while (getcline( &cfile )) {
if (!cfile.cmd) if (!cfile.cmd)
@ -369,6 +372,7 @@ load_config( const char *where, int pseudo )
channel = nfcalloc( sizeof(*channel) ); channel = nfcalloc( sizeof(*channel) );
channel->name = nfstrdup( cfile.val ); channel->name = nfstrdup( cfile.val );
channel->max_messages = global_conf.max_messages; channel->max_messages = global_conf.max_messages;
channel->expire_unread = global_conf.expire_unread;
channel->use_internal_date = global_conf.use_internal_date; channel->use_internal_date = global_conf.use_internal_date;
cops = 0; cops = 0;
max_size = -1; max_size = -1;

1
src/isync.h

@ -167,6 +167,7 @@ typedef struct channel_conf {
string_list_t *patterns; string_list_t *patterns;
int ops[2]; int ops[2];
unsigned max_messages; /* for slave only */ unsigned max_messages; /* for slave only */
signed char expire_unread;
char use_internal_date; char use_internal_date;
} channel_conf_t; } channel_conf_t;

14
src/mbsync.1

@ -400,12 +400,22 @@ This is useful for mailboxes where you keep a complete archive on the server,
but want to mirror only the last messages (for instance, for mailing lists). but want to mirror only the last messages (for instance, for mailing lists).
The messages that were the first to arrive in the mailbox (independently of The messages that were the first to arrive in the mailbox (independently of
the actual date of the message) will be deleted first. the actual date of the message) will be deleted first.
Messages that are flagged (marked as important) and unread messages will not Messages that are flagged (marked as important) and (by default) unread
be automatically deleted. messages will not be automatically deleted.
If \fIcount\fR is 0, the maximum number of messages is \fBunlimited\fR If \fIcount\fR is 0, the maximum number of messages is \fBunlimited\fR
(Default: \fI0\fR). (Default: \fI0\fR).
.. ..
.TP .TP
\fBExpireUnread\fR \fIyes\fR|\fIno\fR
Selects whether unread messages should be affected by \fBMaxMessages\fR.
Normally, unread messages are considered important and thus never expired.
This ensures that you never miss new messages even after an extended absence.
However, if your archive contains large amounts of unread messages by design,
treating them as important would practically defeat \fBMaxMessages\fR. In this
case you need to enable this option.
(Default: \fIno\fR).
..
.TP
\fBSync\fR {\fINone\fR|[\fIPull\fR] [\fIPush\fR] [\fINew\fR] [\fIReNew\fR] [\fIDelete\fR] [\fIFlags\fR]|\fIAll\fR} \fBSync\fR {\fINone\fR|[\fIPull\fR] [\fIPush\fR] [\fINew\fR] [\fIReNew\fR] [\fIDelete\fR] [\fIFlags\fR]|\fIAll\fR}
Select the synchronization operation(s) to perform: Select the synchronization operation(s) to perform:
.br .br

12
src/run-tests.pl

@ -191,6 +191,18 @@ my @X31 = (
); );
test("max messages", \@x30, \@X31, @O31); test("max messages", \@x30, \@X31, @O31);
my @O32 = ("", "", "MaxMessages 3\nExpireUnread yes\n");
#show("30", "32", "32");
my @X32 = (
[ 6,
1, 1, "F", 2, 2, "", 3, 3, "S", 4, 4, "", 5, 5, "S", 6, 6, "" ],
[ 4,
1, 1, "F", 4, 2, "", 5, 3, "S", 6, 4, "" ],
[ 6, 1, 0,
1, 1, "F", 4, 2, "", 5, 3, "S", 6, 4, "" ],
);
test("max messages vs. unread", \@x30, \@X32, @O32);
my @x50 = ( my @x50 = (
[ 6, [ 6,
1, 1, "FS", 2, 2, "FS", 3, 3, "S", 4, 4, "", 5, 5, "", 6, 6, "" ], 1, 1, "FS", 2, 2, "FS", 3, 3, "S", 4, 4, "", 5, 5, "", 6, 6, "" ],

13
src/sync.c

@ -1370,6 +1370,7 @@ box_loaded( int sts, void *aux )
} }
todel = alive - svars->chan->max_messages; todel = alive - svars->chan->max_messages;
debug( "%d alive messages, %d excess - expiring\n", alive, todel ); debug( "%d alive messages, %d excess - expiring\n", alive, todel );
alive = 0;
for (tmsg = svars->ctx[S]->msgs; tmsg; tmsg = tmsg->next) { for (tmsg = svars->ctx[S]->msgs; tmsg; tmsg = tmsg->next) {
if (tmsg->status & M_DEAD) if (tmsg->status & M_DEAD)
continue; continue;
@ -1381,7 +1382,7 @@ box_loaded( int sts, void *aux )
nflags = (tmsg->flags | srec->aflags[S]) & ~srec->dflags[S]; nflags = (tmsg->flags | srec->aflags[S]) & ~srec->dflags[S];
if (!(nflags & F_DELETED) || (srec->status & (S_EXPIRE|S_EXPIRED))) { if (!(nflags & F_DELETED) || (srec->status & (S_EXPIRE|S_EXPIRED))) {
/* The message is not deleted, or is already (being) expired. */ /* The message is not deleted, or is already (being) expired. */
if ((nflags & F_FLAGGED) || !(nflags & F_SEEN)) { if ((nflags & F_FLAGGED) || !((nflags & F_SEEN) || ((void)(todel > 0 && alive++), svars->chan->expire_unread > 0))) {
/* Important messages are always kept. */ /* Important messages are always kept. */
debug( " old pair(%d,%d) important\n", srec->uid[M], srec->uid[S] ); debug( " old pair(%d,%d) important\n", srec->uid[M], srec->uid[S] );
todel--; todel--;
@ -1400,7 +1401,7 @@ box_loaded( int sts, void *aux )
if ((srec = tmsg->srec) && srec->tuid[0]) { if ((srec = tmsg->srec) && srec->tuid[0]) {
nflags = tmsg->flags; nflags = tmsg->flags;
if (!(nflags & F_DELETED)) { if (!(nflags & F_DELETED)) {
if ((nflags & F_FLAGGED) || !(nflags & F_SEEN)) { if ((nflags & F_FLAGGED) || !((nflags & F_SEEN) || ((void)(todel > 0 && alive++), svars->chan->expire_unread > 0))) {
/* Important messages are always fetched. */ /* Important messages are always fetched. */
debug( " new pair(%d,%d) important\n", srec->uid[M], srec->uid[S] ); debug( " new pair(%d,%d) important\n", srec->uid[M], srec->uid[S] );
todel--; todel--;
@ -1415,6 +1416,14 @@ box_loaded( int sts, void *aux )
} }
} }
debug( "%d excess messages remain\n", todel ); debug( "%d excess messages remain\n", todel );
if (svars->chan->expire_unread < 0 && (unsigned)alive * 2 > svars->chan->max_messages) {
error( "%s: %d unread messages in excess of MaxMessages (%d).\n"
"Please set ExpireUnread to decide outcome. Skipping mailbox.\n",
svars->ctx[S]->orig_name, alive, svars->chan->max_messages );
svars->ret |= SYNC_FAIL;
cancel_sync( svars );
return;
}
for (srec = svars->srecs; srec; srec = srec->next) { for (srec = svars->srecs; srec; srec = srec->next) {
if (srec->status & S_DEAD) if (srec->status & S_DEAD)
continue; continue;

Loading…
Cancel
Save