commit 5d5e07eb63b37dba7c37715c44dcbb4518af5b9b
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Wed May 18 22:40:25 2022 +0200

    add --list-stores mode
    
    this is useful for verifying the store configuration, and finding the
    right mailbox names.
    
    REFMAIL: YaZC3XUTWjyfjgn+@ugly

 NEWS            |   2 +
 src/Makefile.am |   2 +-
 src/config.c    |   2 -
 src/driver.c    |   2 +
 src/driver.h    |   2 +
 src/main.c      |  13 +++-
 src/main_list.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/main_p.h    |   1 +
 src/mbsync.1    |   9 +++
 9 files changed, 216 insertions(+), 5 deletions(-)

diff --git a/NEWS b/NEWS
index aa53a198..27eb2c0b 100644
--- a/NEWS
+++ b/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.
diff --git a/src/Makefile.am b/src/Makefile.am
index e7560446..f241db27 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -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 \
diff --git a/src/config.c b/src/config.c
index 880f0271..f932920d 100644
--- a/src/config.c
+++ b/src/config.c
@@ -20,8 +20,6 @@ char FieldDelimiter = ';';
 char FieldDelimiter = ':';
 #endif
 
-static store_conf_t *stores;
-
 char *
 expand_strdup( const char *s, const conffile_t *cfile )
 {
diff --git a/src/driver.c b/src/driver.c
index f5f73bae..05bbb9b0 100644
--- a/src/driver.c
+++ b/src/driver.c
@@ -7,6 +7,8 @@
 
 #include "driver.h"
 
+store_conf_t *stores;
+
 driver_t *drivers[N_DRIVERS] = { &maildir_driver, &imap_driver };
 
 void
diff --git a/src/driver.h b/src/driver.h
index d7c4e3d8..e810bf1f 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -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 */
diff --git a/src/main.c b/src/main.c
index 010397eb..0196db3c 100644
--- a/src/main.c
+++ b/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;
 }
diff --git a/src/main_list.c b/src/main_list.c
new file mode 100644
index 00000000..adda4b9a
--- /dev/null
+++ b/src/main_list.c
@@ -0,0 +1,188 @@
+// SPDX-FileCopyrightText: 2022 Oswald Buddenhagen <o...@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 );
+}
diff --git a/src/main_p.h b/src/main_p.h
index 317367a5..75f619c1 100644
--- a/src/main_p.h
+++ b/src/main_p.h
@@ -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
diff --git a/src/mbsync.1 b/src/mbsync.1
index 403b2ce7..ee54129a 100644
--- a/src/mbsync.1
+++ b/src/mbsync.1
@@ -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


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

Reply via email to