Pārlūkot izejas kodu

establish bi-directional mapping between mails and sync records. use it
to merge the --renew case into the --new case.

Oswald Buddenhagen 19 gadi atpakaļ
vecāks
revīzija
2277ecefb6
2 mainītis faili ar 54 papildinājumiem un 67 dzēšanām
  1. 1 1
      src/isync.h
  2. 53 66
      src/sync.c

+ 1 - 1
src/isync.h

@@ -118,12 +118,12 @@ typedef struct group_conf {
 #define M_RECENT       (1<<0) /* unsyncable flag; maildir_* depend on this being 1<<0 */
 #define M_DEAD         (1<<1) /* expunged */
 #define M_FLAGS        (1<<2) /* flags fetched */
-#define M_PROCESSED    (1<<3) /* registered in pair */
 #define M_SYNCED       (1<<4) /* already propagated */
 #define M_EXPIRED      (1<<5) /* kicked out by MaxMessages */
 
 typedef struct message {
 	struct message *next;
+	struct sync_rec *srec;
 	/* string_list_t *keywords; */
 	size_t size; /* zero implies "not fetched" */
 	int uid;

+ 53 - 66
src/sync.c

@@ -82,6 +82,7 @@ make_flags( int flags, char *buf )
 #define S_EXPIRED      (1<<1)
 #define S_DEL(ms)      (1<<(2+(ms)))
 #define S_EXP_S        (1<<4)
+#define S_DONE         (1<<6)
 
 typedef struct sync_rec {
 	struct sync_rec *next;
@@ -122,10 +123,11 @@ findmsgs( sync_rec_t *srecs, store_t *ctx[], int t )
 				goto found;
 			}
 		}
+		msg->srec = 0;
 		debug( "new\n" );
 		continue;
 	  found:
-		msg->status |= M_PROCESSED;
+		msg->srec = srec;
 		if (srec->uid[1-t] >= 0)
 			msg->status |= M_SYNCED;
 		srec->msg[t] = msg;
@@ -588,48 +590,61 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 		int nmsgs, uid;
 
 		for (nmsgs = 0, tmsg = ctx[1-t]->msgs; tmsg; tmsg = tmsg->next)
-			if (!(tmsg->status & M_PROCESSED)) {
-				if (chan->ops[t] & OP_NEW) {
-					debug( "new message %d on %s\n", tmsg->uid, str_ms[1-t] );
-					if ((chan->ops[t] & OP_EXPUNGE) && (tmsg->flags & F_DELETED)) {
-						debug( "  not %sing - would be expunged anyway\n", str_hl[t] );
+			if (tmsg->srec ? tmsg->srec->uid[t] < 0 && (chan->ops[t] & OP_RENEW) : (chan->ops[t] & OP_NEW)) {
+				debug( "new message %d on %s\n", tmsg->uid, str_ms[1-t] );
+				if ((chan->ops[t] & OP_EXPUNGE) && (tmsg->flags & F_DELETED))
+					debug( "  not %sing - would be expunged anyway\n", str_hl[t] );
+				else {
+					if ((tmsg->flags & F_FLAGGED) || !chan->stores[t]->max_size || tmsg->size <= chan->stores[t]->max_size) {
+						debug( "  %sing it\n", str_hl[t] );
+						if (!nmsgs)
+							info( t ? "Pulling new messages..." : "Pushing new messages..." );
+						else
+							infoc( '.' );
+						nmsgs++;
+						msgdata.flags = tmsg->flags;
+						switch (driver[1-t]->fetch_msg( ctx[1-t], tmsg, &msgdata )) {
+						case DRV_STORE_BAD: return SYNC_BAD(1-t);
+						case DRV_BOX_BAD: return SYNC_FAIL;
+						case DRV_MSG_BAD: /* ok */ continue;
+						}
+						tmsg->flags = msgdata.flags;
+						switch (driver[t]->store_msg( ctx[t], &msgdata, &uid )) {
+						case DRV_STORE_BAD: return SYNC_BAD(t);
+						default: return SYNC_FAIL;
+						case DRV_OK: break;
+						}
 					} else {
-						if ((tmsg->flags & F_FLAGGED) || !chan->stores[t]->max_size || tmsg->size <= chan->stores[t]->max_size) {
-							debug( "  %sing it\n", str_hl[t] );
-							if (!nmsgs)
-								info( t ? "Pulling new messages..." : "Pushing new messages..." );
-							else
-								infoc( '.' );
-							nmsgs++;
-							msgdata.flags = tmsg->flags;
-							switch (driver[1-t]->fetch_msg( ctx[1-t], tmsg, &msgdata )) {
-							case DRV_STORE_BAD: return SYNC_BAD(1-t);
-							case DRV_BOX_BAD: return SYNC_FAIL;
-							case DRV_MSG_BAD: /* ok */ continue;
-							}
-							tmsg->flags = msgdata.flags;
-							switch (driver[t]->store_msg( ctx[t], &msgdata, &uid )) {
-							case DRV_STORE_BAD: return SYNC_BAD(t);
-							default: return SYNC_FAIL;
-							case DRV_OK: tmsg->status |= M_SYNCED; break;
-							}
-						} else {
-							debug( "  not %sing - too big\n", str_hl[t] );
-							uid = -1;
+						if (tmsg->srec) {
+							debug( "  -> not %sing - still too big\n", str_hl[t] );
+							continue;
 						}
+						debug( "  not %sing - too big\n", str_hl[t] );
+						uid = -1;
+					}
+					tmsg->status |= M_SYNCED;
+					if (tmsg->srec) {
+						srec = tmsg->srec;
+						Fprintf( jfp, "%c %d %d %d\n", "<>"[t], srec->uid[M], srec->uid[S], uid );
+					} else {
 						srec = nfmalloc( sizeof(*srec) );
-						srec->uid[1-t] = tmsg->uid;
-						srec->uid[t] = uid;
-						srec->flags = tmsg->flags;
-						srec->status = 0;
 						srec->next = 0;
 						*srecadd = srec;
 						srecadd = &srec->next;
-						Fprintf( jfp, "+ %d %d %u\n", srec->uid[M], srec->uid[S], srec->flags );
+						srec->uid[1-t] = tmsg->uid;
+					}
+					srec->uid[t] = uid;
+					srec->flags = tmsg->flags;
+					srec->status = S_DONE;
+					if (tmsg->srec)
+						Fprintf( jfp, "* %d %d %u\n", srec->uid[M], srec->uid[S], srec->flags );
+					else {
+						tmsg->srec = srec;
 						if (maxuid[1-t] < tmsg->uid) {
 							maxuid[1-t] = tmsg->uid;
 							Fprintf( jfp, "%c %d\n", ")("[t], tmsg->uid );
 						}
+						Fprintf( jfp, "+ %d %d %u\n", srec->uid[M], srec->uid[S], srec->flags );
 					}
 				}
 			}
@@ -640,7 +655,7 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 	debug( "synchronizing old entries\n" );
 	Fprintf( jfp, "^\n" );
 	for (srec = recs; srec != *osrecadd; srec = srec->next) {
-		if (srec->status & S_DEAD)
+		if (srec->status & (S_DEAD|S_DONE))
 			continue;
 		debug( "pair (%d,%d)\n", srec->uid[M], srec->uid[S] );
 		nom = !srec->msg[M] && (ctx[M]->opts & OPEN_OLD);
@@ -656,7 +671,7 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 			nflags = srec->flags;
 
 			for (t = 0; t < 2; t++) {
-				int uid, unex;
+				int unex;
 				unsigned char sflags, aflags, dflags, rflags;
 
 				/* excludes (push) c.3) d.2) d.3) d.4) / (pull) b.3) d.7) d.8) d.9) */
@@ -682,38 +697,10 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan )
 				} else if (!srec->msg[1-t])
 					/* c.1) c.2) d.7) d.8) / b.1) b.2) d.2) d.3) */
 					;
-				else if (srec->uid[t] < 0) {
+				else if (srec->uid[t] < 0)
 					/* b.2) / c.2) */
-					debug( "  no %s yet\n", str_ms[t] );
-					if (chan->ops[t] & OP_RENEW) {
-						if ((chan->ops[t] & OP_EXPUNGE) && (srec->msg[1-t]->flags & F_DELETED)) {
-							debug( "  -> not %sing - would be expunged anyway\n", str_hl[t] );
-						} else {
-							if ((srec->msg[1-t]->flags & F_FLAGGED) || !chan->stores[t]->max_size || srec->msg[1-t]->size <= chan->stores[t]->max_size) {
-								debug( "  -> %sing it\n", str_hl[t] );
-								msgdata.flags = srec->msg[1-t]->flags;
-								switch (driver[1-t]->fetch_msg( ctx[1-t], srec->msg[1-t], &msgdata )) {
-								case DRV_STORE_BAD: ret = SYNC_BAD(1-t); goto finish;
-								case DRV_BOX_BAD: ret = SYNC_FAIL; goto finish;
-								default: /* ok */ break;
-								case DRV_OK:
-									srec->msg[1-t]->flags = msgdata.flags;
-									switch (driver[t]->store_msg( ctx[t], &msgdata, &uid )) {
-									case DRV_STORE_BAD: ret = SYNC_BAD(t); goto finish;
-									default: ret = SYNC_FAIL; goto finish;
-									case DRV_OK:
-										Fprintf( jfp, "%c %d %d %d\n", "<>"[t], srec->uid[M], srec->uid[S], uid );
-										srec->uid[t] = uid;
-										srec->msg[1-t]->status |= M_SYNCED;
-										nflags = srec->msg[1-t]->flags;
-									}
-								}
-							} else {
-								debug( "  -> not %sing - still too big\n", str_hl[t] );
-							}
-						}
-					}
-				} else if (!del[t]) {
+					; /* handled above */
+				else if (!del[t]) {
 					/* a) & b.3) / c.3) */
 					debug( "  may %s\n", str_hl[t] );
 					if (chan->ops[t] & OP_FLAGS) {