ref: 9162533526a8e92a3b111ef2e63f87ae23ad8134
parent: bb94fc197ea706fc302824b91d82a2d3afb08217
author: Ori Bernstein <ori@eigenstate.org>
date: Wed Mar 10 11:49:17 EST 2021
Mail: separate deletion from relinking messages Mutating lists that are being iterated is needlessly error prone, and we were removing the wrong message in some cases if it the dummy got inserted in the right place. Separating deletion into a redraw/relink and zap phase simplifies the problem.
--- a/sys/src/cmd/upas/Mail/mail.h
+++ b/sys/src/cmd/upas/Mail/mail.h
@@ -15,6 +15,7 @@
Sdummy = 1<<0, /* message placeholder */
Stoplev = 1<<1, /* not a response to anything */
Sopen = 1<<2, /* opened for viewing */
+ Szap = 1<<3, /* flushed, to be removed from list */
};
enum {
--- a/sys/src/cmd/upas/Mail/mbox.c
+++ b/sys/src/cmd/upas/Mail/mbox.c
@@ -144,7 +144,7 @@
break;
o += p->child[i]->nsub + 1;
}
- if(!(p->state & Sdummy)){
+ if(!(p->state & (Sdummy|Szap))){
o++;
d++;
}
@@ -157,7 +157,7 @@
break;
if(m->state & Stoplev){
n += mbox.mesg[i]->nsub;
- if(!(m->state & Sdummy))
+ if(!(m->state & (Sdummy|Szap)))
n++;
}
@@ -679,18 +679,17 @@
char *path;
Mesg *m, *p;
- i = 0;
path = estrjoin(maildir, "/ctl", nil);
fd = open(path, OWRITE);
free(path);
if(fd == -1)
sysfatal("open mbox: %r");
- while(i < mbox.nmesg){
+ for(i = 0; i < mbox.nmesg; i++){
m = mbox.mesg[i];
- if((m->state & Sopen) || !(m->flags & (Fdel|Ftodel))){
- i++;
+ p = m->parent;
+ if(m->state & (Sopen|Szap) || (m->flags & (Fdel|Ftodel)) == 0)
continue;
- }
+
ln = mesglineno(m, nil);
fprint(mbox.addr, "%d,%d", ln, ln+m->nsub);
write(mbox.data, "", 0);
@@ -697,20 +696,26 @@
if(m->flags & Ftodel)
fprint(fd, "delete %s %d", mailbox, atoi(m->name));
- p = m->parent;
removeid(m);
+ m->state |= Szap;
if(p == nil && m->nsub != 0){
p = placeholder(m->messageid, m->time, 1);
p->nsub = m->nsub + 1;
- mbox.mesg[i] = p;
}
if(p != nil)
relinkmsg(p, m);
for(j = 0; j < m->nchild; j++)
mbredraw(m->child[j], 1, 1);
- memmove(&mbox.mesg[i], &mbox.mesg[i+1], (mbox.nmesg - i)*sizeof(Mesg*));
- mbox.nmesg--;
}
+
+ for(i = 0, j = 0; i < mbox.nmesg; i++){
+ m = mbox.mesg[i];
+ if((m->state & Szap) != 0)
+ mesgfree(m);
+ else
+ mbox.mesg[j++] = m;
+ }
+
close(fd);
fprint(mbox.ctl, "clean\n");
}