فهرست منبع

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 );
 }