add --list-stores mode
this is useful for verifying the store configuration, and finding the right mailbox names. REFMAIL: YaZC3XUTWjyfjgn+@ugly
This commit is contained in:
parent
d5a5da9475
commit
5d5e07eb63
2
NEWS
2
NEWS
|
@ -6,6 +6,8 @@ The old locations remain supported.
|
|||
The reference point for relative local paths in the configuration file
|
||||
is now the file's containing directory.
|
||||
|
||||
The unfiltered list of mailboxes in each Store can be printed now.
|
||||
|
||||
[1.4.0]
|
||||
|
||||
The 'isync' compatibility wrapper was removed.
|
||||
|
|
|
@ -8,7 +8,7 @@ mbsync_SOURCES = \
|
|||
drv_imap.c \
|
||||
drv_maildir.c \
|
||||
sync.c sync_state.c \
|
||||
main.c main_sync.c
|
||||
main.c main_sync.c main_list.c
|
||||
noinst_HEADERS = \
|
||||
common.h config.h socket.h \
|
||||
driver.h \
|
||||
|
|
|
@ -20,8 +20,6 @@ char FieldDelimiter = ';';
|
|||
char FieldDelimiter = ':';
|
||||
#endif
|
||||
|
||||
static store_conf_t *stores;
|
||||
|
||||
char *
|
||||
expand_strdup( const char *s, const conffile_t *cfile )
|
||||
{
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include "driver.h"
|
||||
|
||||
store_conf_t *stores;
|
||||
|
||||
driver_t *drivers[N_DRIVERS] = { &maildir_driver, &imap_driver };
|
||||
|
||||
void
|
||||
|
|
|
@ -31,6 +31,8 @@ typedef struct store_conf {
|
|||
STORE_CONF
|
||||
} store_conf_t;
|
||||
|
||||
extern store_conf_t *stores;
|
||||
|
||||
/* For message->flags */
|
||||
// Keep the MESSAGE_FLAGS in sync (grep that)!
|
||||
/* The order is according to alphabetical maildir flag sort */
|
||||
|
|
13
src/main.c
13
src/main.c
|
@ -33,6 +33,7 @@ PACKAGE " " VERSION " - mailbox synchronizer\n"
|
|||
" " EXE " [flags] {{channel[:box,...]|group} ...|-a}\n"
|
||||
" -a, --all operate on all defined channels\n"
|
||||
" -l, --list list mailboxes instead of syncing them\n"
|
||||
" -ls, --list-stores raw listing of stores' mailboxes\n"
|
||||
" -n, --new propagate new messages\n"
|
||||
" -d, --delete propagate message deletions\n"
|
||||
" -f, --flags propagate message flag changes\n"
|
||||
|
@ -173,6 +174,8 @@ main( int argc, char **argv )
|
|||
mvars->all = 1;
|
||||
} else if (!strcmp( opt, "list" )) {
|
||||
mvars->list = 1;
|
||||
} else if (!strcmp( opt, "list-stores" )) {
|
||||
mvars->list_stores = 1;
|
||||
} else if (!strcmp( opt, "help" )) {
|
||||
usage( 0 );
|
||||
} else if (!strcmp( opt, "version" )) {
|
||||
|
@ -295,7 +298,10 @@ main( int argc, char **argv )
|
|||
mvars->all = 1;
|
||||
break;
|
||||
case 'l':
|
||||
mvars->list = 1;
|
||||
if (*ochar == 's')
|
||||
mvars->list_stores = 1, ochar++;
|
||||
else
|
||||
mvars->list = 1;
|
||||
break;
|
||||
case 'c':
|
||||
if (oind >= argc) {
|
||||
|
@ -468,6 +474,9 @@ main( int argc, char **argv )
|
|||
if (load_config( config ))
|
||||
return 1;
|
||||
|
||||
sync_chans( mvars, argv + oind );
|
||||
if (mvars->list_stores)
|
||||
list_stores( mvars, argv + oind );
|
||||
else
|
||||
sync_chans( mvars, argv + oind );
|
||||
return mvars->ret;
|
||||
}
|
||||
|
|
188
src/main_list.c
Normal file
188
src/main_list.c
Normal file
|
@ -0,0 +1,188 @@
|
|||
// SPDX-FileCopyrightText: 2022 Oswald Buddenhagen <ossi@users.sf.net>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later WITH LicenseRef-isync-GPL-exception
|
||||
//
|
||||
// mbsync - mailbox synchronizer
|
||||
//
|
||||
|
||||
#include "main_p.h"
|
||||
|
||||
typedef struct store_ent {
|
||||
struct store_ent *next;
|
||||
store_conf_t *conf;
|
||||
} store_ent_t;
|
||||
|
||||
typedef struct {
|
||||
core_vars_t *cvars;
|
||||
store_conf_t *store;
|
||||
driver_t *drv;
|
||||
store_t *ctx;
|
||||
store_ent_t *storeptr;
|
||||
int cben, done;
|
||||
} list_vars_t;
|
||||
|
||||
static store_ent_t *
|
||||
add_store( store_ent_t ***storeapp, store_conf_t *store )
|
||||
{
|
||||
store_ent_t *se = nfzalloc( sizeof(*se) );
|
||||
se->conf = store;
|
||||
**storeapp = se;
|
||||
*storeapp = &se->next;
|
||||
return se;
|
||||
}
|
||||
|
||||
static void do_list_stores( list_vars_t *lvars );
|
||||
static void list_next_store( list_vars_t *lvars );
|
||||
|
||||
void
|
||||
list_stores( core_vars_t *cvars, char **argv )
|
||||
{
|
||||
list_vars_t lvars[1];
|
||||
store_ent_t *strs = NULL, **strapp = &strs;
|
||||
store_conf_t *store;
|
||||
|
||||
memset( lvars, 0, sizeof(*lvars) );
|
||||
lvars->cvars = cvars;
|
||||
|
||||
if (!stores) {
|
||||
fputs( "No stores defined.\n", stderr );
|
||||
cvars->ret = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!*argv) { // Implicit --all
|
||||
for (store = stores; store; store = store->next)
|
||||
add_store( &strapp, store );
|
||||
} else {
|
||||
for (; *argv; argv++) {
|
||||
for (store = stores; store; store = store->next) {
|
||||
if (!strcmp( store->name, *argv )) {
|
||||
add_store( &strapp, store );
|
||||
goto gotstr;
|
||||
}
|
||||
}
|
||||
error( "No store named '%s' defined.\n", *argv );
|
||||
cvars->ret = 1;
|
||||
gotstr: ;
|
||||
}
|
||||
}
|
||||
if (cvars->ret)
|
||||
return;
|
||||
lvars->storeptr = strs;
|
||||
|
||||
do_list_stores( lvars );
|
||||
main_loop();
|
||||
}
|
||||
|
||||
static void
|
||||
list_store_bad( void *aux )
|
||||
{
|
||||
list_vars_t *lvars = (list_vars_t *)aux;
|
||||
|
||||
lvars->drv->cancel_store( lvars->ctx );
|
||||
lvars->cvars->ret = 1;
|
||||
list_next_store( lvars );
|
||||
}
|
||||
|
||||
static void
|
||||
advance_store( list_vars_t *lvars )
|
||||
{
|
||||
store_ent_t *nstr = lvars->storeptr->next;
|
||||
free( lvars->storeptr );
|
||||
lvars->storeptr = nstr;
|
||||
}
|
||||
|
||||
static void list_store_connected( int sts, void *aux );
|
||||
|
||||
static void
|
||||
do_list_stores( list_vars_t *lvars )
|
||||
{
|
||||
while (lvars->storeptr) {
|
||||
lvars->store = lvars->storeptr->conf;
|
||||
lvars->drv = lvars->store->driver;
|
||||
int st = lvars->drv->get_fail_state( lvars->store );
|
||||
if (st != FAIL_TEMP) {
|
||||
info( "Skipping %sfailed store %s.\n",
|
||||
(st == FAIL_WAIT) ? "temporarily " : "", lvars->store->name );
|
||||
lvars->cvars->ret = 1;
|
||||
goto next;
|
||||
}
|
||||
|
||||
uint dcaps = lvars->drv->get_caps( NULL );
|
||||
store_t *ctx = lvars->drv->alloc_store( lvars->store, "" );
|
||||
if ((DFlags & DEBUG_DRV) || ((DFlags & FORCEASYNC) && !(dcaps & DRV_ASYNC))) {
|
||||
lvars->drv = &proxy_driver;
|
||||
ctx = proxy_alloc_store( ctx, "" );
|
||||
}
|
||||
lvars->ctx = ctx;
|
||||
lvars->drv->set_bad_callback( ctx, list_store_bad, lvars );
|
||||
info( "Opening store %s...\n", lvars->store->name );
|
||||
lvars->cben = lvars->done = 0;
|
||||
lvars->drv->connect_store( lvars->ctx, list_store_connected, lvars );
|
||||
if (!lvars->done) {
|
||||
lvars->cben = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
next:
|
||||
advance_store( lvars );
|
||||
}
|
||||
cleanup_drivers();
|
||||
}
|
||||
|
||||
static void
|
||||
list_next_store( list_vars_t *lvars )
|
||||
{
|
||||
if (lvars->cben) {
|
||||
advance_store( lvars );
|
||||
do_list_stores( lvars );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
list_done_store( list_vars_t *lvars )
|
||||
{
|
||||
lvars->done = 1;
|
||||
lvars->drv->free_store( lvars->ctx );
|
||||
list_next_store( lvars );
|
||||
}
|
||||
|
||||
static void list_store_listed( int sts, string_list_t *boxes, void *aux );
|
||||
|
||||
static void
|
||||
list_store_connected( int sts, void *aux )
|
||||
{
|
||||
list_vars_t *lvars = (list_vars_t *)aux;
|
||||
|
||||
switch (sts) {
|
||||
case DRV_CANCELED:
|
||||
return;
|
||||
case DRV_OK:
|
||||
lvars->drv->list_store( lvars->ctx, LIST_INBOX | LIST_PATH_MAYBE, list_store_listed, lvars );
|
||||
break;
|
||||
default:
|
||||
lvars->cvars->ret = 1;
|
||||
list_done_store( lvars );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
list_store_listed( int sts, string_list_t *boxes, void *aux )
|
||||
{
|
||||
list_vars_t *lvars = (list_vars_t *)aux;
|
||||
string_list_t *box;
|
||||
|
||||
switch (sts) {
|
||||
case DRV_CANCELED:
|
||||
return;
|
||||
case DRV_OK:
|
||||
printf( "===== %s:\n", lvars->ctx->conf->name );
|
||||
for (box = boxes; box; box = box->next)
|
||||
puts( box->string );
|
||||
break;
|
||||
default:
|
||||
lvars->cvars->ret = 1;
|
||||
break;
|
||||
}
|
||||
list_done_store( lvars );
|
||||
}
|
|
@ -20,5 +20,6 @@ typedef struct {
|
|||
} core_vars_t;
|
||||
|
||||
void sync_chans( core_vars_t *cvars, char **argv );
|
||||
void list_stores( core_vars_t *cvars, char **argv );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,6 +11,8 @@ mbsync - synchronize IMAP4 and Maildir mailboxes
|
|||
.
|
||||
.SH SYNOPSIS
|
||||
\fBmbsync\fR [\fIoptions\fR ...] {{\fIchannel\fR[\fB:\fIbox\fR[{\fB,\fR|\fB\\n\fR}...]]|\fIgroup\fR} ...|\fB-a\fR}
|
||||
.br
|
||||
\fBmbsync\fR --list-stores [\fIoptions\fR ...] [\fIstore\fR} ...]
|
||||
.
|
||||
.SH DESCRIPTION
|
||||
\fBmbsync\fR is a command line application which synchronizes mailboxes;
|
||||
|
@ -43,6 +45,13 @@ command line are ignored.
|
|||
Don't synchronize anything, but list all mailboxes in the selected Channels
|
||||
and exit.
|
||||
.TP
|
||||
\fB-ls\fR, \fB--list-stores\fR
|
||||
Don't synchronize anything, but list all mailboxes in the selected Stores
|
||||
and exit.
|
||||
If no Stores are specified, all configured ones are listed.
|
||||
These are raw Store contents, not filtered by any Channel's \fBPatterns\fR.
|
||||
This option may be used to verify each Store's configuration.
|
||||
.TP
|
||||
\fB-C\fR[\fBf\fR][\fBn\fR], \fB--create\fR[\fB-far\fR|\fB-near\fR]
|
||||
Override any \fBCreate\fR options from the config file. See below.
|
||||
.TP
|
||||
|
|
Loading…
Reference in New Issue
Block a user