diff --git a/src/main.c b/src/main.c index 780f648..d4424bf 100644 --- a/src/main.c +++ b/src/main.c @@ -144,13 +144,16 @@ matches( const char *t, const char *p ) } static string_list_t * -filter_boxes( string_list_t *boxes, string_list_t *patterns ) +filter_boxes( string_list_t *boxes, const char *prefix, string_list_t *patterns ) { string_list_t *nboxes = 0, *cpat; const char *ps; - int not, fnot; + int not, fnot, pfxl; + pfxl = prefix ? strlen( prefix ) : 0; for (; boxes; boxes = boxes->next) { + if (memcmp( boxes->string, prefix, pfxl )) + continue; fnot = 1; for (cpat = patterns; cpat; cpat = cpat->next) { ps = cpat->string; @@ -159,13 +162,13 @@ filter_boxes( string_list_t *boxes, string_list_t *patterns ) not = 1; } else not = 0; - if (matches( boxes->string, ps )) { + if (matches( boxes->string + pfxl, ps )) { fnot = not; break; } } if (!fnot) - add_string_list( &nboxes, boxes->string ); + add_string_list( &nboxes, boxes->string + pfxl ); } return nboxes; } @@ -195,7 +198,7 @@ typedef struct { driver_t *drv[2]; store_t *ctx[2]; string_list_t *boxes[2], *cboxes, *chanptr; - const char *names[2]; + char *names[2]; char **argv; int oind, ret, multiple, all, list, ops[2], state[2]; char done, skip, cben, boxlist; @@ -504,6 +507,7 @@ static void store_opened( store_t *ctx, void *aux ); static void store_listed( int sts, void *aux ); static int sync_listed_boxes( main_vars_t *mvars, string_list_t *mbox ); static void done_sync_dyn( int sts, void *aux ); +static void done_sync_2_dyn( int sts, void *aux ); static void done_sync( int sts, void *aux ); #define nz(a,b) ((a)?(a):(b)) @@ -601,8 +605,8 @@ sync_chans( main_vars_t *mvars, int ent ) if (!mvars->boxlist && mvars->chan->patterns) { mvars->boxlist = 1; - mvars->boxes[M] = filter_boxes( mvars->ctx[M]->boxes, mvars->chan->patterns ); - mvars->boxes[S] = filter_boxes( mvars->ctx[S]->boxes, mvars->chan->patterns ); + mvars->boxes[M] = filter_boxes( mvars->ctx[M]->boxes, mvars->chan->boxes[M], mvars->chan->patterns ); + mvars->boxes[S] = filter_boxes( mvars->ctx[S]->boxes, mvars->chan->boxes[S], mvars->chan->patterns ); for (mboxp = &mvars->boxes[M]; (mbox = *mboxp); ) { for (sboxp = &mvars->boxes[S]; (sbox = *sboxp); sboxp = &sbox->next) if (!strcmp( sbox->string, mbox->string )) { @@ -710,10 +714,12 @@ store_opened( store_t *ctx, void *aux ) for (flags = 0, cpat = mvars->chan->patterns; cpat; cpat = cpat->next) { const char *pat = cpat->string; if (*pat != '!') { + char buf[8]; + snprintf( buf, sizeof(buf), "%s%s", mvars->chan->boxes[t], pat ); /* Partial matches like "INB*" or even "*" are not considered, * except implicity when the INBOX lives under Path. */ - if (!memcmp( pat, "INBOX", 5 )) { - char c = pat[5]; + if (!memcmp( buf, "INBOX", 5 )) { + char c = buf[5]; if (!c) { /* User really wants the INBOX. */ flags |= LIST_INBOX; @@ -782,12 +788,25 @@ store_listed( int sts, void *aux ) static int sync_listed_boxes( main_vars_t *mvars, string_list_t *mbox ) { - if (!mvars->list) { - mvars->names[M] = mvars->names[S] = mbox->string; - sync_boxes( mvars->ctx, (const char **)mvars->names, mvars->chan, done_sync_dyn, mvars ); - return 1; + if (mvars->chan->boxes[M] || mvars->chan->boxes[S]) { + const char *mpfx = nz( mvars->chan->boxes[M], "" ); + const char *spfx = nz( mvars->chan->boxes[S], "" ); + if (!mvars->list) { + nfasprintf( &mvars->names[M], "%s%s", mpfx, mbox->string ); + nfasprintf( &mvars->names[S], "%s%s", spfx, mbox->string ); + free( mbox ); + sync_boxes( mvars->ctx, (const char **)mvars->names, mvars->chan, done_sync_2_dyn, mvars ); + return 1; + } + printf( "%s%s <=> %s%s\n", mpfx, mbox->string, spfx, mbox->string ); + } else { + if (!mvars->list) { + mvars->names[M] = mvars->names[S] = mbox->string; + sync_boxes( mvars->ctx, (const char **)mvars->names, mvars->chan, done_sync_dyn, mvars ); + return 1; + } + puts( mbox->string ); } - puts( mbox->string ); free( mbox ); return 0; } @@ -801,6 +820,16 @@ done_sync_dyn( int sts, void *aux ) done_sync( sts, aux ); } +static void +done_sync_2_dyn( int sts, void *aux ) +{ + main_vars_t *mvars = (main_vars_t *)aux; + + free( mvars->names[M] ); + free( mvars->names[S] ); + done_sync( sts, aux ); +} + static void done_sync( int sts, void *aux ) { diff --git a/src/mbsync.1 b/src/mbsync.1 index e06d6fe..37a09d9 100644 --- a/src/mbsync.1 +++ b/src/mbsync.1 @@ -367,7 +367,9 @@ Define the Channel \fIname\fR, opening a section for its parameters. .TP {\fBMaster\fR|\fBSlave\fR} \fB:\fIstore\fB:\fR[\fImailbox\fR] Specify the Master resp. Slave Store to be connected by this Channel. -If \fBPatterns\fR are specified, \fImailbox\fR is ignored. +If \fBPatterns\fR are specified, \fImailbox\fR is interpreted as a +prefix which is not matched against the patterns, and which is not +affected by mailbox list overrides. Otherwise, if \fImailbox\fR is omitted, \fBINBOX\fR is assumed. .. .TP diff --git a/src/mbsyncrc.sample b/src/mbsyncrc.sample index f642b3f..f907b3b 100644 --- a/src/mbsyncrc.sample +++ b/src/mbsyncrc.sample @@ -94,3 +94,9 @@ Slave :mirror: Patterns % Group partial o2o:inbox,sent-mail,foobar + +# INBOX => server, INBOX.foo => server.foo, etc. +Channel inbox +Master :server:INBOX +Slave :mirror:server +Patterns *