diff --git a/NEWS b/NEWS index 27eb2c0..b862c24 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,8 @@ is now the file's containing directory. The unfiltered list of mailboxes in each Store can be printed now. +A proper summary is now printed prior to exiting. + [1.4.0] The 'isync' compatibility wrapper was removed. diff --git a/src/main_sync.c b/src/main_sync.c index 4e6ae5a..f1ea700 100644 --- a/src/main_sync.c +++ b/src/main_sync.c @@ -9,6 +9,7 @@ #define nz(a, b) ((a) ? (a) : (b)) +static int ops_any[2], trash_any[2]; static int chans_total, chans_done; static int boxes_total, boxes_done; @@ -37,6 +38,27 @@ stats( void ) progress( "\r%s F: %.*s N: %.*s", buf[2], cls, buf[0], cls, buf[1] ); } +static void +summary( void ) +{ + if (Verbosity < TERSE) + return; + + if (!boxes_done) + return; // Shut up if we errored out early. + + printf( "Processed %d box(es) in %d channel(s)", boxes_done, chans_done ); + for (int t = 2; --t >= 0; ) { + if (ops_any[t]) + printf( ",\n%sed %d new message(s) and %d flag update(s)", + str_hl[t], new_done[t], flags_done[t] ); + if (trash_any[t]) + printf( ",\nmoved %d %s message(s) to trash", + trash_done[t], str_fn[t] ); + } + puts( "." ); +} + static int matches( const char *t, const char *p ) { @@ -165,6 +187,15 @@ add_channel( chan_ent_t ***chanapp, channel_conf_t *chan, int ops[] ) merge_actions( chan, ops, XOP_HAVE_REMOVE, OP_REMOVE, 0 ); merge_actions( chan, ops, XOP_HAVE_EXPUNGE, OP_EXPUNGE, 0 ); + for (int t = 0; t < 2; t++) { + if (chan->ops[t] & OP_MASK_TYPE) + ops_any[t] = 1; + if ((chan->ops[t] & OP_EXPUNGE) && + (chan->stores[t]->trash || + (chan->stores[t^1]->trash && chan->stores[t^1]->trash_remote_new))) + trash_any[t] = 1; + } + **chanapp = ce; *chanapp = &ce->next; chans_total++; @@ -296,8 +327,10 @@ sync_chans( core_vars_t *cvars, char **argv ) stats(); do_sync_chans( mvars ); main_loop(); - if (!cvars->list) + if (!cvars->list) { flushn(); + summary(); + } } enum { diff --git a/src/mbsync.1 b/src/mbsync.1 index 242a901..a681e6f 100644 --- a/src/mbsync.1 +++ b/src/mbsync.1 @@ -102,7 +102,7 @@ Without category specification, all categories except net-all are enabled. .TP \fB-q\fR, \fB--quiet\fR Suppress progress counters (this is implicit if stdout is no TTY, -or any debugging categories are enabled) and notices. +or any debugging categories are enabled), notices, and the summary. If specified twice, suppress warning messages as well. . .SH CONFIGURATION @@ -754,6 +754,9 @@ The message counts represent added messages, messages with updated flags, and trashed messages, respectively. No attempt is made to calculate the totals in advance, so they grow over time as more information is gathered. +.P +Irrespective of output redirection, \fBmbsync\fR will print a summary +of the above in plain language upon completion, except in quiet mode. . .SH RECOMMENDATIONS Make sure your IMAP server does not auto-expunge deleted messages - it is diff --git a/src/util.c b/src/util.c index 1fc2f9d..419c6e1 100644 --- a/src/util.c +++ b/src/util.c @@ -22,7 +22,7 @@ int Pid; char Hostname[256]; const char *Home; -static int need_nl; +static int need_nl, need_del; void flushn( void ) @@ -31,6 +31,16 @@ flushn( void ) putchar( '\n' ); fflush( stdout ); need_nl = 0; + } else if (need_del) { + static const char delstr[] = + " " + " "; + if (need_del > (int)sizeof(delstr) - 1) + need_del = (int)sizeof(delstr) - 1; + // We could use ^[[K instead, but we assume a dumb terminal. + printf( "\r%.*s\r", need_del, delstr ); + fflush( stdout ); + need_del = 0; } } @@ -75,10 +85,9 @@ progress( const char *msg, ... ) va_list va; va_start( va, msg ); - vprintf( msg, va ); + need_del = vprintf( msg, va ) - 1; va_end( va ); fflush( stdout ); - need_nl = 1; } static void ATTR_PRINTFLIKE(1, 0)