瀏覽代碼

make progress counters global

which means they are now cumulative, and include channels and boxes.
Oswald Buddenhagen 10 年之前
父節點
當前提交
8aa22a62e7
共有 5 個文件被更改,包括 108 次插入53 次删除
  1. 6 0
      src/common.h
  2. 2 0
      src/drv_imap.c
  3. 56 5
      src/main.c
  4. 15 0
      src/mbsync.1
  5. 29 48
      src/sync.c

+ 6 - 0
src/common.h

@@ -78,6 +78,12 @@ extern const char *Home;
 
 extern int BufferLimit;
 
+extern int new_total[2], new_done[2];
+extern int flags_total[2], flags_done[2];
+extern int trash_total[2], trash_done[2];
+
+void stats( void );
+
 /* util.c */
 
 void ATTR_PRINTFLIKE(1, 2) debug( const char *, ... );

+ 2 - 0
src/drv_imap.c

@@ -1728,6 +1728,7 @@ ensure_password( imap_server_conf_t *srvc )
 		int ret;
 		char buffer[80];
 
+		flushn();
 		if (!(fp = popen( srvc->pass_cmd, "r" ))) {
 		  pipeerr:
 			sys_error( "Skipping account %s, password command failed", srvc->name );
@@ -1754,6 +1755,7 @@ ensure_password( imap_server_conf_t *srvc )
 	} else if (!srvc->pass) {
 		char *pass, prompt[80];
 
+		flushn();
 		sprintf( prompt, "Password (%s): ", srvc->name );
 		pass = getpass( prompt );
 		if (!pass) {

+ 56 - 5
src/main.c

@@ -45,6 +45,12 @@ const char *Home;	/* for config */
 
 int BufferLimit = 10 * 1024 * 1024;
 
+int chans_total, chans_done;
+int boxes_total, boxes_done;
+int new_total[2], new_done[2];
+int flags_total[2], flags_done[2];
+int trash_total[2], trash_done[2];
+
 static void
 version( void )
 {
@@ -123,6 +129,32 @@ crashHandler( int n )
 }
 #endif
 
+void
+stats( void )
+{
+	char buf[3][64];
+	char *cs;
+	int t, l, ll, cls;
+	static int cols = -1;
+
+	if (DFlags & QUIET)
+		return;
+
+	if (cols < 0 && (!(cs = getenv( "COLUMNS" )) || !(cols = atoi( cs ))))
+		cols = 80;
+	ll = sprintf( buf[2], "C: %d/%d  B: %d/%d", chans_done, chans_total, boxes_done, boxes_total );
+	cls = (cols - ll - 10) / 2;
+	for (t = 0; t < 2; t++) {
+		l = sprintf( buf[t], "+%d/%d *%d/%d #%d/%d",
+		             new_done[t], new_total[t],
+		             flags_done[t], flags_total[t],
+		             trash_done[t], trash_total[t] );
+		if (l > cls)
+			buf[t][cls - 1] = '~';
+	}
+	infon( "\v\r%s  M: %.*s  S: %.*s", buf[2], cls, buf[0], cls, buf[1] );
+}
+
 static int
 matches( const char *t, const char *p )
 {
@@ -254,6 +286,7 @@ add_channel( chan_ent_t ***chanapp, channel_conf_t *chan, int ops[] )
 
 	**chanapp = ce;
 	*chanapp = &ce->next;
+	chans_total++;
 	return ce;
 }
 
@@ -297,8 +330,12 @@ add_named_channel( chan_ent_t ***chanapp, char *channame, int ops[] )
 			mbox->next = 0;
 			*mboxapp = mbox;
 			mboxapp = &mbox->next;
+			boxes_total++;
 			boxp = nboxp;
 		} while (boxp);
+	} else {
+		if (!chan->patterns)
+			boxes_total++;
 	}
 
 	ce = add_channel( chanapp, chan, ops );
@@ -315,7 +352,7 @@ typedef struct {
 	chan_ent_t *chanptr;
 	box_ent_t *boxptr;
 	char *names[2];
-	int ret, multiple, all, list, state[2];
+	int ret, all, list, state[2];
 	char done, skip, cben;
 } main_vars_t;
 
@@ -605,8 +642,11 @@ main( int argc, char **argv )
 	}
 
 	if (mvars->all) {
-		for (chan = channels; chan; chan = chan->next)
+		for (chan = channels; chan; chan = chan->next) {
 			add_channel( &chanapp, chan, ops );
+			if (!chan->patterns)
+				boxes_total++;
+		}
 	} else {
 		for (; argv[oind]; oind++) {
 			for (group = groups; group; group = group->next) {
@@ -627,11 +667,14 @@ main( int argc, char **argv )
 		return 1;
 	}
 	mvars->chanptr = chans;
-	mvars->multiple = !!chans->next;
 
+	if (!mvars->list)
+		stats();
 	mvars->cben = 1;
 	sync_chans( mvars, E_START );
 	main_loop();
+	if (!mvars->list)
+		flushn();
 	return mvars->ret;
 }
 
@@ -723,13 +766,16 @@ sync_chans( main_vars_t *mvars, int ent )
 				mbox->next = 0;
 				*mboxapp = mbox;
 				mboxapp = &mbox->next;
+				boxes_total++;
 			}
 			free( boxes[M] );
 			free( boxes[S] );
+			if (!mvars->list)
+				stats();
 		}
 		mvars->boxptr = mvars->chanptr->boxes;
 
-		if (mvars->list && mvars->multiple)
+		if (mvars->list && chans_total > 1)
 			printf( "%s:\n", mvars->chan->name );
 	  syncml:
 		mvars->done = mvars->cben = 0;
@@ -775,7 +821,10 @@ sync_chans( main_vars_t *mvars, int ent )
 			mvars->chanptr->boxlist = 0;
 		}
 	  next2:
-		;
+		if (!mvars->list) {
+			chans_done++;
+			stats();
+		}
 	} while ((mvars->chanptr = mvars->chanptr->next));
 	for (t = 0; t < N_DRIVERS; t++)
 		drivers[t]->cleanup();
@@ -921,6 +970,8 @@ done_sync( int sts, void *aux )
 	main_vars_t *mvars = (main_vars_t *)aux;
 
 	mvars->done = 1;
+	boxes_done++;
+	stats();
 	if (sts) {
 		mvars->ret = 1;
 		if (sts & (SYNC_BAD(M) | SYNC_BAD(S))) {

+ 15 - 0
src/mbsync.1

@@ -591,6 +591,21 @@ absolute limit, as even a single message can consume more memory than
 this.
 (Default: \fI10M\fR)
 ..
+.SH CONSOLE OUTPUT
+If \fBmbsync\fR's output is connected to a console, it will print progress
+counters by default. The output will look like this:
+.P
+.in +4
+C: 1/2  B: 3/4  M: +13/13 *23/42 #0/0  S: +0/7 *0/0 #0/0
+.in -4
+.P
+This represents the cumulative progress over channels, boxes, and messages
+affected on master and slave, respectively.
+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.
+..
 .SH RECOMMENDATIONS
 Make sure your IMAP server does not auto-expunge deleted messages - it is
 slow, and semantically somewhat questionable. Specifically, Gmail needs to

+ 29 - 48
src/sync.c

@@ -156,9 +156,7 @@ typedef struct {
 	const char *orig_name[2];
 	message_t *new_msgs[2];
 	int state[2], ref_count, nsrecs, ret, lfd, existing, replayed;
-	int new_total[2], new_done[2];
-	int flags_total[2], flags_done[2];
-	int trash_total[2], trash_done[2];
+	int new_pending[2], flags_pending[2], trash_pending[2];
 	int maxuid[2]; /* highest UID that was already propagated */
 	int newmaxuid[2]; /* highest UID that is currently being propagated */
 	int uidval[2]; /* UID validity value */
@@ -446,30 +444,6 @@ msg_stored( int sts, int uid, void *aux )
 }
 
 
-static void
-stats( sync_vars_t *svars )
-{
-	char buf[2][64];
-	char *cs;
-	int t, l;
-	static int cols = -1;
-
-	if (cols < 0 && (!(cs = getenv( "COLUMNS" )) || !(cols = atoi( cs ) / 2)))
-		cols = 36;
-	if (!(DFlags & QUIET)) {
-		for (t = 0; t < 2; t++) {
-			l = sprintf( buf[t], "+%d/%d *%d/%d #%d/%d",
-			             svars->new_done[t], svars->new_total[t],
-			             svars->flags_done[t], svars->flags_total[t],
-			             svars->trash_done[t], svars->trash_total[t] );
-			if (l > cols)
-				buf[t][cols - 1] = '~';
-		}
-		infon( "\v\rM: %.*s  S: %.*s", cols, buf[0], cols, buf[1] );
-	}
-}
-
-
 static void sync_bail( sync_vars_t *svars );
 static void sync_bail2( sync_vars_t *svars );
 static void sync_bail3( sync_vars_t *svars );
@@ -1697,8 +1671,9 @@ box_loaded( int sts, void *aux )
 				dflags &= srec->msg[t]->flags;
 			}
 			if (aflags | dflags) {
-				svars->flags_total[t]++;
-				stats( svars );
+				flags_total[t]++;
+				stats();
+				svars->flags_pending[t]++;
 				fv = nfmalloc( sizeof(*fv) );
 				fv->aux = AUX;
 				fv->srec = srec;
@@ -1756,8 +1731,9 @@ msg_copied( int sts, int uid, copy_vars_t *vars )
 		return;
 	}
 	free( vars );
-	svars->new_done[t]++;
-	stats( svars );
+	new_done[t]++;
+	stats();
+	svars->new_pending[t]--;
 	msgs_copied( svars, t );
 }
 
@@ -1812,8 +1788,9 @@ msgs_copied( sync_vars_t *svars, int t )
 					svars->new_msgs[t] = tmsg;
 					goto out;
 				}
-				svars->new_total[t]++;
-				stats( svars );
+				new_total[t]++;
+				stats();
+				svars->new_pending[t]++;
 				svars->state[t] |= ST_SENDING_NEW;
 				cv = nfmalloc( sizeof(*cv) );
 				cv->cb = msg_copied;
@@ -1829,7 +1806,7 @@ msgs_copied( sync_vars_t *svars, int t )
 		svars->state[t] |= ST_SENT_NEW;
 	}
 
-	if (svars->new_done[t] < svars->new_total[t])
+	if (svars->new_pending[t])
 		goto out;
 
 	Fprintf( svars->jfp, "%c %d\n", ")("[t], svars->maxuid[1-t] );
@@ -1885,8 +1862,9 @@ flags_set( int sts, void *aux )
 		break;
 	}
 	free( vars );
-	svars->flags_done[t]++;
-	stats( svars );
+	flags_done[t]++;
+	stats();
+	svars->flags_pending[t]--;
 	msgs_flags_set( svars, t );
 }
 
@@ -1930,7 +1908,7 @@ msgs_flags_set( sync_vars_t *svars, int t )
 	message_t *tmsg;
 	copy_vars_t *cv;
 
-	if (!(svars->state[t] & ST_SENT_FLAGS) || svars->flags_done[t] < svars->flags_total[t])
+	if (!(svars->state[t] & ST_SENT_FLAGS) || svars->flags_pending[t])
 		return;
 
 	sync_ref( svars );
@@ -1943,8 +1921,9 @@ msgs_flags_set( sync_vars_t *svars, int t )
 				if (svars->ctx[t]->conf->trash) {
 					if (!svars->ctx[t]->conf->trash_only_new || !tmsg->srec || tmsg->srec->uid[1-t] < 0) {
 						debug( "%s: trashing message %d\n", str_ms[t], tmsg->uid );
-						svars->trash_total[t]++;
-						stats( svars );
+						trash_total[t]++;
+						stats();
+						svars->trash_pending[t]++;
 						svars->drv[t]->trash_msg( svars->ctx[t], tmsg, msg_trashed, AUX );
 						if (check_cancel( svars ))
 							goto out;
@@ -1954,8 +1933,9 @@ msgs_flags_set( sync_vars_t *svars, int t )
 					if (!tmsg->srec || tmsg->srec->uid[1-t] < 0) {
 						if (tmsg->size <= svars->ctx[1-t]->conf->max_size) {
 							debug( "%s: remote trashing message %d\n", str_ms[t], tmsg->uid );
-							svars->trash_total[t]++;
-							stats( svars );
+							trash_total[t]++;
+							stats();
+							svars->trash_pending[t]++;
 							cv = nfmalloc( sizeof(*cv) );
 							cv->cb = msg_rtrashed;
 							cv->aux = INV_AUX;
@@ -1988,8 +1968,9 @@ msg_trashed( int sts, void *aux )
 	if (check_ret( sts, aux ))
 		return;
 	INIT_SVARS(aux);
-	svars->trash_done[t]++;
-	stats( svars );
+	trash_done[t]++;
+	stats();
+	svars->trash_pending[t]--;
 	sync_close( svars, t );
 }
 
@@ -2008,8 +1989,9 @@ msg_rtrashed( int sts, int uid ATTR_UNUSED, copy_vars_t *vars )
 	}
 	free( vars );
 	t ^= 1;
-	svars->trash_done[t]++;
-	stats( svars );
+	trash_done[t]++;
+	stats();
+	svars->trash_pending[t]--;
 	sync_close( svars, t );
 }
 
@@ -2019,8 +2001,8 @@ static void box_closed_p2( sync_vars_t *svars, int t );
 static void
 sync_close( sync_vars_t *svars, int t )
 {
-	if ((~svars->state[t] & (ST_FOUND_NEW|ST_SENT_TRASH)) || svars->trash_done[t] < svars->trash_total[t] ||
-	    !(svars->state[1-t] & ST_SENT_NEW) || svars->new_done[1-t] < svars->new_total[1-t])
+	if ((~svars->state[t] & (ST_FOUND_NEW|ST_SENT_TRASH)) || svars->trash_pending[t] ||
+	    !(svars->state[1-t] & ST_SENT_NEW) || svars->new_pending[1-t])
 		return;
 
 	if (svars->state[t] & ST_CLOSING)
@@ -2120,7 +2102,6 @@ sync_bail2( sync_vars_t *svars )
 	free( svars->nname );
 	free( svars->jname );
 	free( svars->dname );
-	flushn();
 	sync_bail3( svars );
 }