seqmap: sync seqNum to uid after expunge
This patch updates the seqNums after an Expunge operation. When an expunge operation occurs, the seqNum of the deleted message is reported. The Imap spec [0] states that an immediate decrement of all seqnums greater than the deleted occurs, even before the next reporting of an expunge update. [0]: https://datatracker.ietf.org/doc/html/rfc3501#section-7.4.1 Fixes: https://todo.sr.ht/~rjarry/aerc/61 Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Signed-off-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
parent
9bfcec5660
commit
fb5558da81
2 changed files with 20 additions and 5 deletions
|
@ -1,6 +1,8 @@
|
||||||
package imap
|
package imap
|
||||||
|
|
||||||
import "sync"
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
type SeqMap struct {
|
type SeqMap struct {
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
|
@ -35,7 +37,17 @@ func (s *SeqMap) Pop(seqnum uint32) (uint32, bool) {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
uid, found := s.m[seqnum]
|
uid, found := s.m[seqnum]
|
||||||
if found {
|
if found {
|
||||||
delete(s.m, seqnum)
|
m := make(map[uint32]uint32)
|
||||||
|
for s, u := range s.m {
|
||||||
|
if s > seqnum {
|
||||||
|
// All sequence numbers greater than the removed one must be decremented by one
|
||||||
|
// https://datatracker.ietf.org/doc/html/rfc3501#section-7.4.1
|
||||||
|
m[s-1] = u
|
||||||
|
} else if s < seqnum {
|
||||||
|
m[s] = u
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.m = m
|
||||||
}
|
}
|
||||||
s.lock.Unlock()
|
s.lock.Unlock()
|
||||||
return uid, found
|
return uid, found
|
||||||
|
|
|
@ -39,12 +39,15 @@ func TestSeqMap(t *testing.T) {
|
||||||
assert.Equal(found, true)
|
assert.Equal(found, true)
|
||||||
assert.Equal(seqmap.Size(), 2)
|
assert.Equal(seqmap.Size(), 2)
|
||||||
|
|
||||||
|
// Repop the same seqnum should work because of the syncing
|
||||||
_, found = seqmap.Pop(1)
|
_, found = seqmap.Pop(1)
|
||||||
assert.Equal(found, false)
|
assert.Equal(found, true)
|
||||||
assert.Equal(seqmap.Size(), 2)
|
assert.Equal(seqmap.Size(), 1)
|
||||||
|
|
||||||
|
// sync means we already have a 1. This is replacing that UID so the size
|
||||||
|
// shouldn't increase
|
||||||
seqmap.Put(1, 7331)
|
seqmap.Put(1, 7331)
|
||||||
assert.Equal(seqmap.Size(), 3)
|
assert.Equal(seqmap.Size(), 1)
|
||||||
|
|
||||||
seqmap.Clear()
|
seqmap.Clear()
|
||||||
assert.Equal(seqmap.Size(), 0)
|
assert.Equal(seqmap.Size(), 0)
|
||||||
|
|
Loading…
Reference in a new issue