aboutsummaryrefslogtreecommitdiffstats
path: root/worker
diff options
context:
space:
mode:
Diffstat (limited to 'worker')
-rw-r--r--worker/imap/cache.go12
-rw-r--r--worker/imap/extensions/xgmext/client.go21
-rw-r--r--worker/imap/fetch.go22
-rw-r--r--worker/imap/flags.go6
-rw-r--r--worker/imap/imap.go8
-rw-r--r--worker/imap/list.go2
-rw-r--r--worker/imap/open.go8
-rw-r--r--worker/imap/worker.go4
-rw-r--r--worker/jmap/directories.go8
-rw-r--r--worker/jmap/fetch.go22
-rw-r--r--worker/jmap/jmap.go2
-rw-r--r--worker/jmap/push.go5
-rw-r--r--worker/jmap/set.go26
-rw-r--r--worker/jmap/worker.go3
-rw-r--r--worker/lib/search.go4
-rw-r--r--worker/lib/sort.go4
-rw-r--r--worker/maildir/container.go73
-rw-r--r--worker/maildir/message.go4
-rw-r--r--worker/maildir/search.go9
-rw-r--r--worker/maildir/worker.go16
-rw-r--r--worker/mbox/io.go7
-rw-r--r--worker/mbox/models.go42
-rw-r--r--worker/mbox/worker.go6
-rw-r--r--worker/notmuch/lib/database.go14
-rw-r--r--worker/notmuch/message.go4
-rw-r--r--worker/notmuch/worker.go28
-rw-r--r--worker/types/messages.go32
-rw-r--r--worker/types/thread.go29
-rw-r--r--worker/types/thread_test.go86
29 files changed, 224 insertions, 283 deletions
diff --git a/worker/imap/cache.go b/worker/imap/cache.go
index 8ae60f03..0eba7b9d 100644
--- a/worker/imap/cache.go
+++ b/worker/imap/cache.go
@@ -24,7 +24,7 @@ type CachedHeader struct {
BodyStructure models.BodyStructure
Envelope models.Envelope
InternalDate time.Time
- Uid uint32
+ Uid models.UID
Size uint32
Header []byte
Created time.Time
@@ -34,7 +34,7 @@ var (
// cacheTag should be updated when changing the cache
// structure; this will ensure that the user's cache is cleared and
// reloaded when the underlying cache structure changes
- cacheTag = []byte("0002")
+ cacheTag = []byte("0003")
cacheTagKey = []byte("cache.tag")
)
@@ -112,9 +112,9 @@ func (w *IMAPWorker) cacheHeader(mi *models.MessageInfo) {
}
}
-func (w *IMAPWorker) getCachedHeaders(msg *types.FetchMessageHeaders) []uint32 {
+func (w *IMAPWorker) getCachedHeaders(msg *types.FetchMessageHeaders) []models.UID {
w.worker.Tracef("Retrieving headers from cache: %v", msg.Uids)
- var need []uint32
+ var need []models.UID
for _, uid := range msg.Uids {
key := w.headerKey(uid)
data, err := w.cache.Get(key, nil)
@@ -157,8 +157,8 @@ func (w *IMAPWorker) getCachedHeaders(msg *types.FetchMessageHeaders) []uint32 {
return need
}
-func (w *IMAPWorker) headerKey(uid uint32) []byte {
- key := fmt.Sprintf("header.%s.%d.%d",
+func (w *IMAPWorker) headerKey(uid models.UID) []byte {
+ key := fmt.Sprintf("header.%s.%d.%s",
w.selected.Name, w.selected.UidValidity, uid)
return []byte(key)
}
diff --git a/worker/imap/extensions/xgmext/client.go b/worker/imap/extensions/xgmext/client.go
index 65f11e74..e6e34a44 100644
--- a/worker/imap/extensions/xgmext/client.go
+++ b/worker/imap/extensions/xgmext/client.go
@@ -5,6 +5,7 @@ import (
"fmt"
"git.sr.ht/~rjarry/aerc/lib/log"
+ "git.sr.ht/~rjarry/aerc/models"
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
"github.com/emersion/go-imap/commands"
@@ -19,7 +20,7 @@ func NewHandler(c *client.Client) *handler {
return &handler{client: c}
}
-func (h handler) FetchEntireThreads(requested []uint32) ([]uint32, error) {
+func (h handler) FetchEntireThreads(requested []models.UID) ([]models.UID, error) {
threadIds, err := h.fetchThreadIds(requested)
if err != nil {
return nil,
@@ -33,7 +34,7 @@ func (h handler) FetchEntireThreads(requested []uint32) ([]uint32, error) {
return uids, nil
}
-func (h handler) fetchThreadIds(uids []uint32) ([]string, error) {
+func (h handler) fetchThreadIds(uids []models.UID) ([]string, error) {
messages := make(chan *imap.Message)
done := make(chan error)
@@ -58,7 +59,9 @@ func (h handler) fetchThreadIds(uids []uint32) ([]string, error) {
}()
var set imap.SeqSet
- set.AddNum(uids...)
+ for _, uid := range uids {
+ set.AddNum(models.UidToUint32(uid))
+ }
err := h.client.UidFetch(&set, items, messages)
<-done
@@ -69,18 +72,18 @@ func (h handler) fetchThreadIds(uids []uint32) ([]string, error) {
return thrid, err
}
-func (h handler) searchUids(thrid []string) ([]uint32, error) {
+func (h handler) searchUids(thrid []string) ([]models.UID, error) {
if len(thrid) == 0 {
return nil, errors.New("no thread IDs provided")
}
return h.runSearch(NewThreadIDSearch(thrid))
}
-func (h handler) RawSearch(rawSearch string) ([]uint32, error) {
+func (h handler) RawSearch(rawSearch string) ([]models.UID, error) {
return h.runSearch(NewRawSearch(rawSearch))
}
-func (h handler) runSearch(cmd imap.Commander) ([]uint32, error) {
+func (h handler) runSearch(cmd imap.Commander) ([]models.UID, error) {
if h.client.State() != imap.SelectedState {
return nil, errors.New("no mailbox selected")
}
@@ -90,5 +93,9 @@ func (h handler) runSearch(cmd imap.Commander) ([]uint32, error) {
if err != nil {
return nil, fmt.Errorf("imap execute failed: %w", err)
}
- return res.Ids, status.Err()
+ var uids []models.UID
+ for _, i := range res.Ids {
+ uids = append(uids, models.Uint32ToUid(i))
+ }
+ return uids, status.Err()
}
diff --git a/worker/imap/fetch.go b/worker/imap/fetch.go
index 202038fe..9b77c777 100644
--- a/worker/imap/fetch.go
+++ b/worker/imap/fetch.go
@@ -82,7 +82,7 @@ func (imapw *IMAPWorker) handleFetchMessageHeaders(
RFC822Headers: header,
Refs: parse.MsgIDList(header, "references"),
Size: _msg.Size,
- Uid: _msg.Uid,
+ Uid: models.Uint32ToUid(_msg.Uid),
}
imapw.worker.PostMessage(&types.MessageInfo{
Message: types.RespondTo(msg),
@@ -126,7 +126,7 @@ func (imapw *IMAPWorker) handleFetchMessageBodyPart(
partHeaderSection.FetchItem(),
partBodySection.FetchItem(),
}
- imapw.handleFetchMessages(msg, []uint32{msg.Uid}, items,
+ imapw.handleFetchMessages(msg, []models.UID{msg.Uid}, items,
func(_msg *imap.Message) error {
if len(_msg.Body) == 0 {
// ignore duplicate messages with only flag updates
@@ -154,7 +154,7 @@ func (imapw *IMAPWorker) handleFetchMessageBodyPart(
Message: types.RespondTo(msg),
Part: &models.MessageBodyPart{
Reader: part.Body,
- Uid: _msg.Uid,
+ Uid: models.Uint32ToUid(_msg.Uid),
},
}, nil)
// Update flags (to mark message as read)
@@ -162,7 +162,7 @@ func (imapw *IMAPWorker) handleFetchMessageBodyPart(
Message: types.RespondTo(msg),
Info: &models.MessageInfo{
Flags: translateImapFlags(_msg.Flags),
- Uid: _msg.Uid,
+ Uid: models.Uint32ToUid(_msg.Uid),
},
}, nil)
return nil
@@ -196,7 +196,7 @@ func (imapw *IMAPWorker) handleFetchFullMessages(
Message: types.RespondTo(msg),
Content: &models.FullMessage{
Reader: bufio.NewReader(r),
- Uid: _msg.Uid,
+ Uid: models.Uint32ToUid(_msg.Uid),
},
}, nil)
// Update flags (to mark message as read)
@@ -204,7 +204,7 @@ func (imapw *IMAPWorker) handleFetchFullMessages(
Message: types.RespondTo(msg),
Info: &models.MessageInfo{
Flags: translateImapFlags(_msg.Flags),
- Uid: _msg.Uid,
+ Uid: models.Uint32ToUid(_msg.Uid),
},
}, nil)
return nil
@@ -228,7 +228,7 @@ func (imapw *IMAPWorker) handleFetchMessageFlags(msg *types.FetchMessageFlags) {
Message: types.RespondTo(msg),
Info: &models.MessageInfo{
Flags: translateImapFlags(_msg.Flags),
- Uid: _msg.Uid,
+ Uid: models.Uint32ToUid(_msg.Uid),
},
}, nil)
return nil
@@ -236,13 +236,13 @@ func (imapw *IMAPWorker) handleFetchMessageFlags(msg *types.FetchMessageFlags) {
}
func (imapw *IMAPWorker) handleFetchMessages(
- msg types.WorkerMessage, uids []uint32, items []imap.FetchItem,
+ msg types.WorkerMessage, uids []models.UID, items []imap.FetchItem,
procFunc func(*imap.Message) error,
) {
messages := make(chan *imap.Message)
done := make(chan struct{})
- missingUids := make(map[uint32]bool)
+ missingUids := make(map[models.UID]bool)
for _, uid := range uids {
missingUids[uid] = true
}
@@ -251,14 +251,14 @@ func (imapw *IMAPWorker) handleFetchMessages(
defer log.PanicHandler()
for _msg := range messages {
- delete(missingUids, _msg.Uid)
+ delete(missingUids, models.Uint32ToUid(_msg.Uid))
err := procFunc(_msg)
if err != nil {
log.Errorf("failed to process message <%d>: %v", _msg.Uid, err)
imapw.worker.PostMessage(&types.MessageInfo{
Message: types.RespondTo(msg),
Info: &models.MessageInfo{
- Uid: _msg.Uid,
+ Uid: models.Uint32ToUid(_msg.Uid),
Error: err,
},
}, nil)
diff --git a/worker/imap/flags.go b/worker/imap/flags.go
index 60137bd3..31d3bea3 100644
--- a/worker/imap/flags.go
+++ b/worker/imap/flags.go
@@ -81,7 +81,7 @@ func (imapw *IMAPWorker) handleAnsweredMessages(msg *types.AnsweredMessages) {
Message: types.RespondTo(msg),
Info: &models.MessageInfo{
Flags: translateImapFlags(_msg.Flags),
- Uid: _msg.Uid,
+ Uid: models.Uint32ToUid(_msg.Uid),
},
}, nil)
return nil
@@ -100,7 +100,7 @@ func (imapw *IMAPWorker) handleFlagMessages(msg *types.FlagMessages) {
Message: types.RespondTo(msg),
Info: &models.MessageInfo{
Flags: translateImapFlags(_msg.Flags),
- Uid: _msg.Uid,
+ Uid: models.Uint32ToUid(_msg.Uid),
},
}, nil)
return nil
@@ -108,7 +108,7 @@ func (imapw *IMAPWorker) handleFlagMessages(msg *types.FlagMessages) {
}
func (imapw *IMAPWorker) handleStoreOps(
- msg types.WorkerMessage, uids []uint32, item imap.StoreItem, flag interface{},
+ msg types.WorkerMessage, uids []models.UID, item imap.StoreItem, flag interface{},
procFunc func(*imap.Message) error,
) {
messages := make(chan *imap.Message)
diff --git a/worker/imap/imap.go b/worker/imap/imap.go
index fbdcb2b9..67d56264 100644
--- a/worker/imap/imap.go
+++ b/worker/imap/imap.go
@@ -14,12 +14,12 @@ func init() {
imap.CharsetReader = charset.Reader
}
-func toSeqSet(uids []uint32) *imap.SeqSet {
- var set imap.SeqSet
+func toSeqSet(uids []models.UID) *imap.SeqSet {
+ set := new(imap.SeqSet)
for _, uid := range uids {
- set.AddNum(uid)
+ set.AddNum(models.UidToUint32(uid))
}
- return &set
+ return set
}
func translateBodyStructure(bs *imap.BodyStructure) *models.BodyStructure {
diff --git a/worker/imap/list.go b/worker/imap/list.go
index d12ae4bd..e3c9db3e 100644
--- a/worker/imap/list.go
+++ b/worker/imap/list.go
@@ -139,6 +139,6 @@ func (imapw *IMAPWorker) handleSearchDirectory(msg *types.SearchDirectory) {
imapw.worker.PostMessage(&types.SearchResults{
Message: types.RespondTo(msg),
- Uids: uids,
+ Uids: models.Uint32ToUidList(uids),
}, nil)
}
diff --git a/worker/imap/open.go b/worker/imap/open.go
index 355709a7..b1314a4b 100644
--- a/worker/imap/open.go
+++ b/worker/imap/open.go
@@ -5,6 +5,7 @@ import (
sortthread "github.com/emersion/go-imap-sortthread"
+ "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/worker/types"
)
@@ -85,9 +86,10 @@ func (imapw *IMAPWorker) handleFetchDirectoryContents(
// Only initialize if we are not filtering
imapw.seqMap.Initialize(uids)
}
+
imapw.worker.PostMessage(&types.DirectoryContents{
Message: types.RespondTo(msg),
- Uids: uids,
+ Uids: models.Uint32ToUidList(uids),
}, nil)
imapw.worker.PostMessage(&types.Done{Message: types.RespondTo(msg)}, nil)
}
@@ -146,7 +148,7 @@ func (imapw *IMAPWorker) handleDirectoryThreaded(
var uids []uint32
for i := len(aercThreads) - 1; i >= 0; i-- {
aercThreads[i].Walk(func(t *types.Thread, level int, currentErr error) error { //nolint:errcheck // error indicates skipped threads
- uids = append(uids, t.Uid)
+ uids = append(uids, models.UidToUint32(t.Uid))
return nil
})
}
@@ -175,7 +177,7 @@ func convertThreads(threads []*sortthread.Thread, parent *types.Thread) ([]*type
for i := 0; i < len(threads); i++ {
t := threads[i]
conv[i] = &types.Thread{
- Uid: t.Id,
+ Uid: models.Uint32ToUid(t.Id),
}
// Set the first child node
diff --git a/worker/imap/worker.go b/worker/imap/worker.go
index edb68ec4..28eb907c 100644
--- a/worker/imap/worker.go
+++ b/worker/imap/worker.go
@@ -289,7 +289,7 @@ func (w *IMAPWorker) handleImapUpdate(update client.Update) {
Envelope: translateEnvelope(msg.Envelope),
Flags: translateImapFlags(msg.Flags),
InternalDate: msg.InternalDate,
- Uid: msg.Uid,
+ Uid: models.Uint32ToUid(msg.Uid),
},
}, nil)
case *client.ExpungeUpdate:
@@ -297,7 +297,7 @@ func (w *IMAPWorker) handleImapUpdate(update client.Update) {
w.worker.Errorf("ExpungeUpdate unknown seqnum: %d", update.SeqNum)
} else {
w.worker.PostMessage(&types.MessagesDeleted{
- Uids: []uint32{uid},
+ Uids: []models.UID{models.Uint32ToUid(uid)},
}, nil)
}
}
diff --git a/worker/jmap/directories.go b/worker/jmap/directories.go
index 07bb0762..7ae79ead 100644
--- a/worker/jmap/directories.go
+++ b/worker/jmap/directories.go
@@ -186,9 +186,9 @@ func (w *JMAPWorker) handleFetchDirectoryContents(msg *types.FetchDirectoryConte
}
}
- uids := make([]uint32, 0, len(contents.MessageIDs))
+ uids := make([]models.UID, 0, len(contents.MessageIDs))
for _, id := range contents.MessageIDs {
- uids = append(uids, w.uidStore.GetOrInsert(string(id)))
+ uids = append(uids, models.UID(id))
}
w.w.PostMessage(&types.DirectoryContents{
Message: types.RespondTo(msg),
@@ -214,9 +214,9 @@ func (w *JMAPWorker) handleSearchDirectory(msg *types.SearchDirectory) error {
for _, inv := range resp.Responses {
switch r := inv.Args.(type) {
case *email.QueryResponse:
- var uids []uint32
+ var uids []models.UID
for _, id := range r.IDs {
- uids = append(uids, w.uidStore.GetOrInsert(string(id)))
+ uids = append(uids, models.UID(id))
}
w.w.PostMessage(&types.SearchResults{
Message: types.RespondTo(msg),
diff --git a/worker/jmap/fetch.go b/worker/jmap/fetch.go
index 07579b99..3b3a8460 100644
--- a/worker/jmap/fetch.go
+++ b/worker/jmap/fetch.go
@@ -38,11 +38,7 @@ func (w *JMAPWorker) handleFetchMessageHeaders(msg *types.FetchMessageHeaders) e
emailIdsToFetch := make([]jmap.ID, 0, len(msg.Uids))
currentEmails := make([]*email.Email, 0, len(msg.Uids))
for _, uid := range msg.Uids {
- id, ok := w.uidStore.GetKey(uid)
- if !ok {
- return fmt.Errorf("bug: no jmap id for message uid: %v", uid)
- }
- jid := jmap.ID(id)
+ jid := jmap.ID(uid)
m, err := w.cache.GetEmail(jid)
if err != nil {
// Message wasn't in cache; fetch it
@@ -103,13 +99,9 @@ func (w *JMAPWorker) handleFetchMessageHeaders(msg *types.FetchMessageHeaders) e
}
func (w *JMAPWorker) handleFetchMessageBodyPart(msg *types.FetchMessageBodyPart) error {
- id, ok := w.uidStore.GetKey(msg.Uid)
- if !ok {
- return fmt.Errorf("bug: unknown message uid %d", msg.Uid)
- }
- mail, err := w.cache.GetEmail(jmap.ID(id))
+ mail, err := w.cache.GetEmail(jmap.ID(msg.Uid))
if err != nil {
- return fmt.Errorf("bug: unknown message id %s: %w", id, err)
+ return fmt.Errorf("bug: unknown message id %s: %w", msg.Uid, err)
}
part := mail.BodyStructure
@@ -159,13 +151,9 @@ func (w *JMAPWorker) handleFetchMessageBodyPart(msg *types.FetchMessageBodyPart)
func (w *JMAPWorker) handleFetchFullMessages(msg *types.FetchFullMessages) error {
for _, uid := range msg.Uids {
- id, ok := w.uidStore.GetKey(uid)
- if !ok {
- return fmt.Errorf("bug: unknown message uid %d", uid)
- }
- mail, err := w.cache.GetEmail(jmap.ID(id))
+ mail, err := w.cache.GetEmail(jmap.ID(uid))
if err != nil {
- return fmt.Errorf("bug: unknown message id %s: %w", id, err)
+ return fmt.Errorf("bug: unknown message id %s: %w", uid, err)
}
buf, err := w.cache.GetBlob(mail.BlobID)
if err != nil {
diff --git a/worker/jmap/jmap.go b/worker/jmap/jmap.go
index bb0f75f9..7320ec04 100644
--- a/worker/jmap/jmap.go
+++ b/worker/jmap/jmap.go
@@ -37,7 +37,7 @@ func (w *JMAPWorker) translateMsgInfo(m *email.Email) *models.MessageInfo {
return &models.MessageInfo{
Envelope: env,
Flags: keywordsToFlags(m.Keywords),
- Uid: w.uidStore.GetOrInsert(string(m.ID)),
+ Uid: models.UID(m.ID),
BodyStructure: translateBodyStructure(m.BodyStructure),
RFC822Headers: translateJMAPHeader(m.Headers),
Refs: m.References,
diff --git a/worker/jmap/push.go b/worker/jmap/push.go
index bc90dd77..f2a8ad45 100644
--- a/worker/jmap/push.go
+++ b/worker/jmap/push.go
@@ -247,10 +247,9 @@ func (w *JMAPWorker) refresh(newState jmap.TypeState) error {
}
if w.selectedMbox == mboxId {
- uids := make([]uint32, 0, len(ids))
+ uids := make([]models.UID, 0, len(ids))
for _, id := range ids {
- uid := w.uidStore.GetOrInsert(string(id))
- uids = append(uids, uid)
+ uids = append(uids, models.UID(id))
}
w.w.PostMessage(&types.DirectoryContents{
Uids: uids,
diff --git a/worker/jmap/set.go b/worker/jmap/set.go
index 36b23688..302314c1 100644
--- a/worker/jmap/set.go
+++ b/worker/jmap/set.go
@@ -10,15 +10,11 @@ import (
"git.sr.ht/~rockorager/go-jmap/mail/mailbox"
)
-func (w *JMAPWorker) updateFlags(uids []uint32, flags models.Flags, enable bool) error {
+func (w *JMAPWorker) updateFlags(uids []models.UID, flags models.Flags, enable bool) error {
var req jmap.Request
patches := make(map[jmap.ID]jmap.Patch)
for _, uid := range uids {
- id, ok := w.uidStore.GetKey(uid)
- if !ok {
- return fmt.Errorf("bug: unknown uid %d", uid)
- }
patch := jmap.Patch{}
for kw := range flagsToKeywords(flags) {
path := fmt.Sprintf("keywords/%s", kw)
@@ -28,7 +24,7 @@ func (w *JMAPWorker) updateFlags(uids []uint32, flags models.Flags, enable bool)
patch[path] = nil
}
}
- patches[jmap.ID(id)] = patch
+ patches[jmap.ID(uid)] = patch
}
req.Invoke(&email.Set{
@@ -44,7 +40,7 @@ func (w *JMAPWorker) updateFlags(uids []uint32, flags models.Flags, enable bool)
return checkNotUpdated(resp)
}
-func (w *JMAPWorker) moveCopy(uids []uint32, destDir string, deleteSrc bool) error {
+func (w *JMAPWorker) moveCopy(uids []models.UID, destDir string, deleteSrc bool) error {
var req jmap.Request
var destMbox jmap.ID
var destroy []jmap.ID
@@ -62,13 +58,9 @@ func (w *JMAPWorker) moveCopy(uids []uint32, destDir string, deleteSrc bool) err
for _, uid := range uids {
dest := destMbox
- id, ok := w.uidStore.GetKey(uid)
- if !ok {
- return fmt.Errorf("bug: unknown uid %d", uid)
- }
- mail, err := w.cache.GetEmail(jmap.ID(id))
+ mail, err := w.cache.GetEmail(jmap.ID(uid))
if err != nil {
- return fmt.Errorf("bug: unknown message id %s: %w", id, err)
+ return fmt.Errorf("bug: unknown message id %s: %w", uid, err)
}
patch := w.moveCopyPatch(mail, dest, deleteSrc)
@@ -76,7 +68,7 @@ func (w *JMAPWorker) moveCopy(uids []uint32, destDir string, deleteSrc bool) err
destroy = append(destroy, mail.ID)
w.w.Debugf("destroying <%s>", mail.MessageID[0])
} else {
- patches[jmap.ID(id)] = patch
+ patches[jmap.ID(uid)] = patch
}
}
@@ -161,11 +153,7 @@ func (w *JMAPWorker) handleModifyLabels(msg *types.ModifyLabels) error {
patches := make(map[jmap.ID]jmap.Patch)
for _, uid := range msg.Uids {
- id, ok := w.uidStore.GetKey(uid)
- if !ok {
- return fmt.Errorf("bug: unknown uid %d", uid)
- }
- patches[jmap.ID(id)] = patch
+ patches[jmap.ID(uid)] = patch
}
req.Invoke(&email.Set{
diff --git a/worker/jmap/worker.go b/worker/jmap/worker.go
index 67553272..58883e1e 100644
--- a/worker/jmap/worker.go
+++ b/worker/jmap/worker.go
@@ -6,7 +6,6 @@ import (
"time"
"git.sr.ht/~rjarry/aerc/config"
- "git.sr.ht/~rjarry/aerc/lib/uidstore"
"git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/worker/handlers"
"git.sr.ht/~rjarry/aerc/worker/jmap/cache"
@@ -47,7 +46,6 @@ type JMAPWorker struct {
mbox2dir map[jmap.ID]string
roles map[mailbox.Role]jmap.ID
identities map[string]*identity.Identity
- uidStore *uidstore.Store
changes chan jmap.TypeState
stop chan struct{}
@@ -56,7 +54,6 @@ type JMAPWorker struct {
func NewJMAPWorker(worker *types.Worker) (types.Backend, error) {
return &JMAPWorker{
w: worker,
- uidStore: uidstore.NewStore(),
roles: make(map[mailbox.Role]jmap.ID),
dir2mbox: make(map[string]jmap.ID),
mbox2dir: make(map[jmap.ID]string),
diff --git a/worker/lib/search.go b/worker/lib/search.go
index d44e2ce1..b98e2bbb 100644
--- a/worker/lib/search.go
+++ b/worker/lib/search.go
@@ -13,11 +13,11 @@ import (
"git.sr.ht/~rjarry/go-opt"
)
-func Search(messages []rfc822.RawMessage, criteria *types.SearchCriteria) ([]uint32, error) {
+func Search(messages []rfc822.RawMessage, criteria *types.SearchCriteria) ([]models.UID, error) {
criteria.PrepareHeader()
requiredParts := GetRequiredParts(criteria)
- matchedUids := []uint32{}
+ var matchedUids []models.UID
for _, m := range messages {
success, err := SearchMessage(m, criteria, requiredParts)
if err != nil {
diff --git a/worker/lib/sort.go b/worker/lib/sort.go
index 7af2c6fa..70a64c7b 100644
--- a/worker/lib/sort.go
+++ b/worker/lib/sort.go
@@ -11,7 +11,7 @@ import (
func Sort(messageInfos []*models.MessageInfo,
criteria []*types.SortCriterion,
-) ([]uint32, error) {
+) ([]models.UID, error) {
// loop through in reverse to ensure we sort by non-primary fields first
for i := len(criteria) - 1; i >= 0; i-- {
criterion := criteria[i]
@@ -56,7 +56,7 @@ func Sort(messageInfos []*models.MessageInfo,
})
}
}
- var uids []uint32
+ var uids []models.UID
// copy in reverse as msgList displays backwards
for i := len(messageInfos) - 1; i >= 0; i-- {
uids = append(uids, messageInfos[i].Uid)
diff --git a/worker/maildir/container.go b/worker/maildir/container.go
index dea1ded6..c23825da 100644
--- a/worker/maildir/container.go
+++ b/worker/maildir/container.go
@@ -9,7 +9,7 @@ import (
"github.com/emersion/go-maildir"
"git.sr.ht/~rjarry/aerc/lib/log"
- "git.sr.ht/~rjarry/aerc/lib/uidstore"
+ "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/worker/lib"
)
@@ -17,8 +17,7 @@ import (
// the Maildir spec
type Container struct {
Store *lib.MaildirStore
- uids *uidstore.Store
- recentUIDS map[uint32]struct{} // used to set the recent flag
+ recentUIDS map[models.UID]struct{} // used to set the recent flag
}
// NewContainer creates a new container at the specified directory
@@ -28,8 +27,8 @@ func NewContainer(dir string, maildirpp bool) (*Container, error) {
return nil, err
}
return &Container{
- Store: store, uids: uidstore.NewStore(),
- recentUIDS: make(map[uint32]struct{}),
+ Store: store,
+ recentUIDS: make(map[models.UID]struct{}),
}, nil
}
@@ -40,8 +39,7 @@ func (c *Container) SyncNewMail(dir maildir.Dir) error {
return err
}
for _, key := range keys {
- uid := c.uids.GetOrInsert(key)
- c.recentUIDS[uid] = struct{}{}
+ c.recentUIDS[models.UID(key)] = struct{}{}
}
return nil
}
@@ -57,18 +55,18 @@ func (c *Container) OpenDirectory(name string) (maildir.Dir, error) {
}
// IsRecent returns if a uid has the Recent flag set
-func (c *Container) IsRecent(uid uint32) bool {
+func (c *Container) IsRecent(uid models.UID) bool {
_, ok := c.recentUIDS[uid]
return ok
}
// ClearRecentFlag removes the Recent flag from the message with the given uid
-func (c *Container) ClearRecentFlag(uid uint32) {
+func (c *Container) ClearRecentFlag(uid models.UID) {
delete(c.recentUIDS, uid)
}
// UIDs fetches the unique message identifiers for the maildir
-func (c *Container) UIDs(d maildir.Dir) ([]uint32, error) {
+func (c *Container) UIDs(d maildir.Dir) ([]models.UID, error) {
keys, err := d.Keys()
if err != nil && len(keys) == 0 {
return nil, fmt.Errorf("could not get keys for %s: %w", d, err)
@@ -77,39 +75,26 @@ func (c *Container) UIDs(d maildir.Dir) ([]uint32, error) {
log.Errorf("could not get all keys for %s: %s", d, err.Error())
}
sort.Strings(keys)
- var uids []uint32
+ var uids []models.UID
for _, key := range keys {
- uids = append(uids, c.uids.GetOrInsert(key))
+ uids = append(uids, models.UID(key))
}
return uids, err
}
// Message returns a Message struct for the given UID and maildir
-func (c *Container) Message(d maildir.Dir, uid uint32) (*Message, error) {
- if key, ok := c.uids.GetKey(uid); ok {
- return &Message{
- dir: d,
- uid: uid,
- key: key,
- }, nil
- }
- return nil, fmt.Errorf("could not find message with uid %d in maildir %s",
- uid, d)
-}
-
-func (c *Container) MessageFromKey(d maildir.Dir, key string) *Message {
- uid := c.uids.GetOrInsert(key)
+func (c *Container) Message(d maildir.Dir, uid models.UID) (*Message, error) {
return &Message{
dir: d,
uid: uid,
- key: key,
- }
+ key: string(uid),
+ }, nil
}
// DeleteAll deletes a set of messages by UID and returns the subset of UIDs
// which were successfully deleted, stopping upon the first error.
-func (c *Container) DeleteAll(d maildir.Dir, uids []uint32) ([]uint32, error) {
- var success []uint32
+func (c *Container) DeleteAll(d maildir.Dir, uids []models.UID) ([]models.UID, error) {
+ var success []models.UID
for _, uid := range uids {
msg, err := c.Message(d, uid)
if err != nil {
@@ -124,46 +109,38 @@ func (c *Container) DeleteAll(d maildir.Dir, uids []uint32) ([]uint32, error) {
}
func (c *Container) CopyAll(
- dest maildir.Dir, src maildir.Dir, uids []uint32,
+ dest maildir.Dir, src maildir.Dir, uids []models.UID,
) error {
for _, uid := range uids {
if err := c.copyMessage(dest, src, uid); err != nil {
- return fmt.Errorf("could not copy message %d: %w", uid, err)
+ return fmt.Errorf("could not copy message %s: %w", uid, err)
}
}
return nil
}
func (c *Container) copyMessage(
- dest maildir.Dir, src maildir.Dir, uid uint32,
+ dest maildir.Dir, src maildir.Dir, uid models.UID,
) error {
- key, ok := c.uids.GetKey(uid)
- if !ok {
- return fmt.Errorf("could not find key for message id %d", uid)
- }
- _, err := src.Copy(dest, key)
+ _, err := src.Copy(dest, string(uid))
return err
}
-func (c *Container) MoveAll(dest maildir.Dir, src maildir.Dir, uids []uint32) ([]uint32, error) {
- var success []uint32
+func (c *Container) MoveAll(dest maildir.Dir, src maildir.Dir, uids []models.UID) ([]models.UID, error) {
+ var success []models.UID
for _, uid := range uids {
if err := c.moveMessage(dest, src, uid); err != nil {
- return success, fmt.Errorf("could not move message %d: %w", uid, err)
+ return success, fmt.Errorf("could not move message %s: %w", uid, err)
}
success = append(success, uid)
}
return success, nil
}
-func (c *Container) moveMessage(dest maildir.Dir, src maildir.Dir, uid uint32) error {
- key, ok := c.uids.GetKey(uid)
- if !ok {
- return fmt.Errorf("could not find key for message id %d", uid)
- }
- path, err := src.Filename(key)
+func (c *Container) moveMessage(dest maildir.Dir, src maildir.Dir, uid models.UID) error {
+ path, err := src.Filename(string(uid))
if err != nil {
- return fmt.Errorf("could not find path for message id %d", uid)
+ return fmt.Errorf("could not find path for message id %s: %w", uid, err)
}
// Remove encoded UID information from the key to prevent sync issues
name := lib.StripUIDFromMessageFilename(filepath.Base(path))
diff --git a/worker/maildir/message.go b/worker/maildir/message.go
index 1d8d26b9..14c83721 100644
--- a/worker/maildir/message.go
+++ b/worker/maildir/message.go
@@ -15,7 +15,7 @@ import (
// A Message is an individual email inside of a maildir.Dir.
type Message struct {
dir maildir.Dir
- uid uint32
+ uid models.UID
key string
}
@@ -135,7 +135,7 @@ func (m Message) NewBodyPartReader(requestedParts []int) (io.Reader, error) {
return rfc822.FetchEntityPartReader(msg, requestedParts)
}
-func (m Message) UID() uint32 {
+func (m Message) UID() models.UID {
return m.uid
}
diff --git a/worker/maildir/search.go b/worker/maildir/search.go
index 90c84087..de2d0530 100644
--- a/worker/maildir/search.go
+++ b/worker/maildir/search.go
@@ -6,11 +6,12 @@ import (
"sync"
"git.sr.ht/~rjarry/aerc/lib/log"
+ "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/worker/lib"
"git.sr.ht/~rjarry/aerc/worker/types"
)
-func (w *Worker) search(ctx context.Context, criteria *types.SearchCriteria) ([]uint32, error) {
+func (w *Worker) search(ctx context.Context, criteria *types.SearchCriteria) ([]models.UID, error) {
criteria.PrepareHeader()
requiredParts := lib.GetRequiredParts(criteria)
w.worker.Debugf("Required parts bitmask for search: %b", requiredParts)
@@ -20,7 +21,7 @@ func (w *Worker) search(ctx context.Context, criteria *types.SearchCriteria) ([]
return nil, err
}
- matchedUids := []uint32{}
+ var matchedUids []models.UID
mu := sync.Mutex{}
wg := sync.WaitGroup{}
// Hard limit at 2x CPU cores
@@ -33,7 +34,7 @@ func (w *Worker) search(ctx context.Context, criteria *types.SearchCriteria) ([]
default:
limit <- struct{}{}
wg.Add(1)
- go func(key uint32) {
+ go func(key models.UID) {
defer log.PanicHandler()
defer wg.Done()
success, err := w.searchKey(key, criteria, requiredParts)
@@ -55,7 +56,7 @@ func (w *Worker) search(ctx context.Context, criteria *types.SearchCriteria) ([]
}
// Execute the search criteria for the given key, returns true if search succeeded
-func (w *Worker) searchKey(key uint32, criteria *types.SearchCriteria,
+func (w *Worker) searchKey(key models.UID, criteria *types.SearchCriteria,
parts lib.MsgParts,
) (bool, error) {
message, err := w.c.Message(*w.selected, key)
diff --git a/worker/maildir/worker.go b/worker/maildir/worker.go
index 2c5bc893..74efdc3c 100644
--- a/worker/maildir/worker.go
+++ b/worker/maildir/worker.go
@@ -460,7 +460,7 @@ func (w *Worker) handleFetchDirectoryContents(
msg *types.FetchDirectoryContents,
) error {
var (
- uids []uint32
+ uids []models.UID
err error
)
if msg.Filter != nil {
@@ -494,7 +494,7 @@ func (w *Worker) handleFetchDirectoryContents(
return nil
}
-func (w *Worker) sort(ctx context.Context, uids []uint32, criteria []*types.SortCriterion) ([]uint32, error) {
+func (w *Worker) sort(ctx context.Context, uids []models.UID, criteria []*types.SortCriterion) ([]models.UID, error) {
if len(criteria) == 0 {
// At least sort by uid, parallel searching can create random
// order
@@ -516,7 +516,7 @@ func (w *Worker) sort(ctx context.Context, uids []uint32, criteria []*types.Sort
default:
limit <- struct{}{}
wg.Add(1)
- go func(uid uint32) {
+ go func(uid models.UID) {
defer log.PanicHandler()
defer wg.Done()
info, err := w.msgHeadersFromUid(uid)
@@ -546,7 +546,7 @@ func (w *Worker) handleFetchDirectoryThreaded(
msg *types.FetchDirectoryThreaded,
) error {
var (
- uids []uint32
+ uids []models.UID
err error
)
if msg.Filter != nil {
@@ -574,7 +574,7 @@ func (w *Worker) handleFetchDirectoryThreaded(
return nil
}
-func (w *Worker) threads(ctx context.Context, uids []uint32,
+func (w *Worker) threads(ctx context.Context, uids []models.UID,
criteria []*types.SortCriterion,
) ([]*types.Thread, error) {
builder := aercLib.NewThreadBuilder(iterator.NewFactory(false), false)
@@ -590,7 +590,7 @@ func (w *Worker) threads(ctx context.Context, uids []uint32,
default:
limit <- struct{}{}
wg.Add(1)
- go func(uid uint32) {
+ go func(uid models.UID) {
defer log.PanicHandler()
defer wg.Done()
info, err := w.msgHeadersFromUid(uid)
@@ -903,7 +903,7 @@ func (w *Worker) handleSearchDirectory(msg *types.SearchDirectory) error {
return nil
}
-func (w *Worker) msgInfoFromUid(uid uint32) (*models.MessageInfo, error) {
+func (w *Worker) msgInfoFromUid(uid models.UID) (*models.MessageInfo, error) {
m, err := w.c.Message(*w.selected, uid)
if err != nil {
return nil, err
@@ -923,7 +923,7 @@ func (w *Worker) msgInfoFromUid(uid uint32) (*models.MessageInfo, error) {
return info, nil
}
-func (w *Worker) msgHeadersFromUid(uid uint32) (*models.MessageInfo, error) {
+func (w *Worker) msgHeadersFromUid(uid models.UID) (*models.MessageInfo, error) {
m, err := w.c.Message(*w.selected, uid)
if err != nil {
return nil, err
diff --git a/worker/mbox/io.go b/worker/mbox/io.go
index f5fbc596..22d0d023 100644
--- a/worker/mbox/io.go
+++ b/worker/mbox/io.go
@@ -12,7 +12,6 @@ import (
func Read(r io.Reader) ([]rfc822.RawMessage, error) {
mbr := mbox.NewReader(r)
- uid := uint32(0)
messages := make([]rfc822.RawMessage, 0)
for {
msg, err := mbr.NextMessage()
@@ -28,10 +27,10 @@ func Read(r io.Reader) ([]rfc822.RawMessage, error) {
}
messages = append(messages, &message{
- uid: uid, flags: models.SeenFlag, content: content,
+ uid: uidFromContents(content),
+ flags: models.SeenFlag,
+ content: content,
})
-
- uid++
}
return messages, nil
}
diff --git a/worker/mbox/models.go b/worker/mbox/models.go
index 5acd6f5a..ebfe5d32 100644
--- a/worker/mbox/models.go
+++ b/worker/mbox/models.go
@@ -2,6 +2,8 @@ package mboxer
import (
"bytes"
+ "crypto/sha256"
+ "encoding/hex"
"fmt"
"io"
@@ -49,7 +51,7 @@ func (md *mailboxContainer) DirectoryInfo(file string) *models.DirectoryInfo {
}
}
-func (md *mailboxContainer) Copy(dest, src string, uids []uint32) error {
+func (md *mailboxContainer) Copy(dest, src string, uids []models.UID) error {
srcmbox, ok := md.Mailbox(src)
if !ok {
return fmt.Errorf("source %s not found", src)
@@ -69,15 +71,15 @@ func (md *mailboxContainer) Copy(dest, src string, uids []uint32) error {
if found {
msg, err := srcmbox.Message(uidSrc)
if err != nil {
- return fmt.Errorf("could not get message with uid %d from folder %s", uidSrc, src)
+ return fmt.Errorf("could not get message with uid %s from folder %s", uidSrc, src)
}
r, err := msg.NewReader()
if err != nil {
- return fmt.Errorf("could not get reader for message with uid %d", uidSrc)
+ return fmt.Errorf("could not get reader for message with uid %s", uidSrc)
}
flags, err := msg.ModelFlags()
if err != nil {
- return fmt.Errorf("could not get flags for message with uid %d", uidSrc)
+ return fmt.Errorf("could not get flags for message with uid %s", uidSrc)
}
err = destmbox.Append(r, flags)
if err != nil {
@@ -94,24 +96,24 @@ type container struct {
messages []rfc822.RawMessage
}
-func (f *container) Uids() []uint32 {
- uids := make([]uint32, len(f.messages))
+func (f *container) Uids() []models.UID {
+ uids := make([]models.UID, len(f.messages))
for i, m := range f.messages {
uids[i] = m.UID()
}
return uids
}
-func (f *container) Message(uid uint32) (rfc822.RawMessage, error) {
+func (f *container) Message(uid models.UID) (rfc822.RawMessage, error) {
for _, m := range f.messages {
if uid == m.UID() {
return m, nil
}
}
- return &message{}, fmt.Errorf("uid [%d] not found", uid)
+ return &message{}, fmt.Errorf("uid [%s] not found", uid)
}
-func (f *container) Delete(uids []uint32) (deleted []uint32) {
+func (f *container) Delete(uids []models.UID) (deleted []models.UID) {
newMessages := make([]rfc822.RawMessage, 0)
for _, m := range f.messages {
del := false
@@ -131,32 +133,28 @@ func (f *container) Delete(uids []uint32) (deleted []uint32) {
return
}
-func (f *container) newUid() (next uint32) {
- for _, m := range f.messages {
- if uid := m.UID(); uid > next {
- next = uid
- }
- }
- next++
- return
-}
-
func (f *container) Append(r io.Reader, flags models.Flags) error {
data, err := io.ReadAll(r)
if err != nil {
return err
}
f.messages = append(f.messages, &message{
- uid: f.newUid(),
+ uid: uidFromContents(data),
flags: flags,
content: data,
})
return nil
}
+func uidFromContents(data []byte) models.UID {
+ sum := sha256.New()
+ sum.Write(data)
+ return models.UID(hex.EncodeToString(sum.Sum(nil)))
+}
+
// message implements the lib.RawMessage interface
type message struct {
- uid uint32
+ uid models.UID
flags models.Flags
content []byte
}
@@ -173,7 +171,7 @@ func (m *message) Labels() ([]string, error) {
return nil, nil
}
-func (m *message) UID() uint32 {
+func (m *message) UID() models.UID {
return m.uid
}
diff --git a/worker/mbox/worker.go b/worker/mbox/worker.go
index 1f4a4965..72a44368 100644
--- a/worker/mbox/worker.go
+++ b/worker/mbox/worker.go
@@ -405,7 +405,7 @@ func (w *mboxWorker) PathSeparator() string {
return "/"
}
-func filterUids(folder *container, uids []uint32, criteria *types.SearchCriteria) ([]uint32, error) {
+func filterUids(folder *container, uids []models.UID, criteria *types.SearchCriteria) ([]models.UID, error) {
log.Debugf("Search with parsed criteria: %#v", criteria)
m := make([]rfc822.RawMessage, 0, len(uids))
for _, uid := range uids {
@@ -419,9 +419,9 @@ func filterUids(folder *container, uids []uint32, criteria *types.SearchCriteria
return lib.Search(m, criteria)
}
-func sortUids(folder *container, uids []uint32,
+func sortUids(folder *container, uids []models.UID,
criteria []*types.SortCriterion,
-) ([]uint32, error) {
+) ([]models.UID, error) {
var infos []*models.MessageInfo
needSize := false
for _, item := range criteria {
diff --git a/worker/notmuch/lib/database.go b/worker/notmuch/lib/database.go
index 9a8a9a60..2915605d 100644
--- a/worker/notmuch/lib/database.go
+++ b/worker/notmuch/lib/database.go
@@ -10,7 +10,7 @@ import (
"git.sr.ht/~rjarry/aerc/lib/log"
"git.sr.ht/~rjarry/aerc/lib/notmuch"
- "git.sr.ht/~rjarry/aerc/lib/uidstore"
+ "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/worker/types"
)
@@ -18,7 +18,6 @@ type DB struct {
path string
excludedTags []string
db *notmuch.Database
- uidStore *uidstore.Store
}
func NewDB(path string, excludedTags []string) *DB {
@@ -28,7 +27,6 @@ func NewDB(path string, excludedTags []string) *DB {
db := &DB{
path: path,
excludedTags: excludedTags,
- uidStore: uidstore.NewStore(),
db: nm,
}
return db
@@ -312,14 +310,6 @@ func (db *DB) MsgModifyTags(key string, add, remove []string) error {
return msg.SyncTagsToMaildirFlags()
}
-func (db *DB) UidFromKey(key string) uint32 {
- return db.uidStore.GetOrInsert(key)
-}
-
-func (db *DB) KeyFromUid(uid uint32) (string, bool) {
- return db.uidStore.GetKey(uid)
-}
-
func (db *DB) makeThread(parent *types.Thread, msgs *notmuch.Messages, threadContext bool) []*types.Thread {
var siblings []*types.Thread
for msgs.Next() {
@@ -338,7 +328,7 @@ func (db *DB) makeThread(parent *types.Thread, msgs *notmuch.Messages, threadCon
continue
}
node := &types.Thread{
- Uid: db.uidStore.GetOrInsert(msgID),
+ Uid: models.UID(msgID),
Parent: parent,
}
switch threadContext {
diff --git a/worker/notmuch/message.go b/worker/notmuch/message.go
index 539d85ae..81a4da54 100644
--- a/worker/notmuch/message.go
+++ b/worker/notmuch/message.go
@@ -21,7 +21,7 @@ import (
)
type Message struct {
- uid uint32
+ uid models.UID
key string
db *notmuch.DB
}
@@ -152,7 +152,7 @@ func (m *Message) ModelFlags() (models.Flags, error) {
return flags, nil
}
-func (m *Message) UID() uint32 {
+func (m *Message) UID() models.UID {
return m.uid
}
diff --git a/worker/notmuch/worker.go b/worker/notmuch/worker.go
index 06c0cde6..8c954a61 100644
--- a/worker/notmuch/worker.go
+++ b/worker/notmuch/worker.go
@@ -457,27 +457,21 @@ func (w *worker) handleFetchMessageHeaders(
return nil
}
-func (w *worker) uidsFromQuery(ctx context.Context, query string) ([]uint32, error) {
+func (w *worker) uidsFromQuery(ctx context.Context, query string) ([]models.UID, error) {
msgIDs, err := w.db.MsgIDsFromQuery(ctx, query)
if err != nil {
return nil, err
}
- var uids []uint32
+ var uids []models.UID
for _, id := range msgIDs {
- uid := w.db.UidFromKey(id)
- uids = append(uids, uid)
-
+ uids = append(uids, models.UID(id))
}
return uids, nil
}
-func (w *worker) msgFromUid(uid uint32) (*Message, error) {
- key, ok := w.db.KeyFromUid(uid)
- if !ok {
- return nil, fmt.Errorf("Invalid uid: %v", uid)
- }
+func (w *worker) msgFromUid(uid models.UID) (*Message, error) {
msg := &Message{
- key: key,
+ key: string(uid),
uid: uid,
db: w.db,
}
@@ -613,7 +607,7 @@ func (w *worker) handleModifyLabels(msg *types.ModifyLabels) error {
for _, uid := range msg.Uids {
m, err := w.msgFromUid(uid)
if err != nil {
- return fmt.Errorf("could not get message from uid %d: %w", uid, err)
+ return fmt.Errorf("could not get message from uid %s: %w", uid, err)
}
err = m.ModifyTags(msg.Add, msg.Remove)
if err != nil {
@@ -699,7 +693,7 @@ func (w *worker) emitDirectoryThreaded(parent types.WorkerMessage) error {
return nil
}
-func (w *worker) emitMessageInfoError(msg types.WorkerMessage, uid uint32, err error) {
+func (w *worker) emitMessageInfoError(msg types.WorkerMessage, uid models.UID, err error) {
w.w.PostMessage(&types.MessageInfo{
Info: &models.MessageInfo{
Envelope: &models.Envelope{},
@@ -743,9 +737,9 @@ func (w *worker) emitLabelList() {
w.w.PostMessage(&types.LabelList{Labels: tags}, nil)
}
-func (w *worker) sort(uids []uint32,
+func (w *worker) sort(uids []models.UID,
criteria []*types.SortCriterion,
-) ([]uint32, error) {
+) ([]models.UID, error) {
if len(criteria) == 0 {
return uids, nil
}
@@ -796,7 +790,7 @@ func (w *worker) handleDeleteMessages(msg *types.DeleteMessages) error {
return errUnsupported
}
- var deleted []uint32
+ var deleted []models.UID
folders, _ := w.store.FolderMap()
curDir := folders[w.currentQueryName]
@@ -874,7 +868,7 @@ func (w *worker) handleMoveMessages(msg *types.MoveMessages) error {
return errUnsupported
}
- var moved []uint32
+ var moved []models.UID
folders, _ := w.store.FolderMap()
diff --git a/worker/types/messages.go b/worker/types/messages.go
index b91adbb7..0d0a187a 100644
--- a/worker/types/messages.go
+++ b/worker/types/messages.go
@@ -146,29 +146,29 @@ type RemoveDirectory struct {
type FetchMessageHeaders struct {
Message
Context context.Context
- Uids []uint32
+ Uids []models.UID
}
type FetchFullMessages struct {
Message
- Uids []uint32
+ Uids []models.UID
}
type FetchMessageBodyPart struct {
Message
- Uid uint32
+ Uid models.UID
Part []int
}
type FetchMessageFlags struct {
Message
Context context.Context
- Uids []uint32
+ Uids []models.UID
}
type DeleteMessages struct {
Message
- Uids []uint32
+ Uids []models.UID
MultiFileStrategy *MultiFileStrategy
}
@@ -177,32 +177,32 @@ type FlagMessages struct {
Message
Enable bool
Flags models.Flags
- Uids []uint32
+ Uids []models.UID
}
type AnsweredMessages struct {
Message
Answered bool
- Uids []uint32
+ Uids []models.UID
}
type ForwardedMessages struct {
Message
Forwarded bool
- Uids []uint32
+ Uids []models.UID
}
type CopyMessages struct {
Message
Destination string
- Uids []uint32
+ Uids []models.UID
MultiFileStrategy *MultiFileStrategy
}
type MoveMessages struct {
Message
Destination string
- Uids []uint32
+ Uids []models.UID
MultiFileStrategy *MultiFileStrategy
}
@@ -244,12 +244,12 @@ type DirectoryInfo struct {
type DirectoryContents struct {
Message
- Uids []uint32
+ Uids []models.UID
}
type SearchResults struct {
Message
- Uids []uint32
+ Uids []models.UID
}
type MessageInfo struct {
@@ -270,24 +270,24 @@ type MessageBodyPart struct {
type MessagesDeleted struct {
Message
- Uids []uint32
+ Uids []models.UID
}
type MessagesCopied struct {
Message
Destination string
- Uids []uint32
+ Uids []models.UID
}
type MessagesMoved struct {
Message
Destination string
- Uids []uint32
+ Uids []models.UID
}
type ModifyLabels struct {
Message
- Uids []uint32
+ Uids []models.UID
Add []string
Remove []string
}
diff --git a/worker/types/thread.go b/worker/types/thread.go
index 42565964..fe6c56bf 100644
--- a/worker/types/thread.go
+++ b/worker/types/thread.go
@@ -6,10 +6,11 @@ import (
"sort"
"git.sr.ht/~rjarry/aerc/lib/log"
+ "git.sr.ht/~rjarry/aerc/models"
)
type Thread struct {
- Uid uint32
+ Uid models.UID
Parent *Thread
PrevSibling *Thread
NextSibling *Thread
@@ -77,11 +78,11 @@ func (t *Thread) Root() *Thread {
}
// Uids returns all associated uids for the given thread and its children
-func (t *Thread) Uids() []uint32 {
+func (t *Thread) Uids() []models.UID {
if t == nil {
return nil
}
- uids := make([]uint32, 0)
+ uids := make([]models.UID, 0)
err := t.Walk(func(node *Thread, _ int, _ error) error {
uids = append(uids, node.Uid)
return nil
@@ -96,20 +97,20 @@ func (t *Thread) String() string {
if t == nil {
return "<nil>"
}
- parent := -1
+ var parent models.UID
if t.Parent != nil {
- parent = int(t.Parent.Uid)
+ parent = t.Parent.Uid
}
- next := -1
+ var next models.UID
if t.NextSibling != nil {
- next = int(t.NextSibling.Uid)
+ next = t.NextSibling.Uid
}
- child := -1
+ var child models.UID
if t.FirstChild != nil {
- child = int(t.FirstChild.Uid)
+ child = t.FirstChild.Uid
}
return fmt.Sprintf(
- "[%d] (parent:%v, next:%v, child:%v)",
+ "[%s] (parent:%s, next:%s, child:%s)",
t.Uid, parent, next, child,
)
}
@@ -141,9 +142,9 @@ type NewThreadWalkFn func(t *Thread, level int, currentErr error) error
// Implement interface to be able to sort threads by newest (max UID)
type ByUID []*Thread
-func getMaxUID(thread *Thread) uint32 {
+func getMaxUID(thread *Thread) models.UID {
// TODO: should we make this part of the Thread type to avoid recomputation?
- var Uid uint32
+ var Uid models.UID
_ = thread.Walk(func(t *Thread, _ int, currentErr error) error {
if t.Deleted || t.Hidden > 0 {
@@ -171,9 +172,9 @@ func (s ByUID) Less(i, j int) bool {
return maxUID_i < maxUID_j
}
-func SortThreadsBy(toSort []*Thread, sortBy []uint32) {
+func SortThreadsBy(toSort []*Thread, sortBy []models.UID) {
// build a map from sortBy
- uidMap := make(map[uint32]int)
+ uidMap := make(map[models.UID]int)
for i, uid := range sortBy {
uidMap[uid] = i
}
diff --git a/worker/types/thread_test.go b/worker/types/thread_test.go
index 669803d8..a6a0f327 100644
--- a/worker/types/thread_test.go
+++ b/worker/types/thread_test.go
@@ -4,16 +4,16 @@ import (
"fmt"
"strings"
"testing"
+
+ "git.sr.ht/~rjarry/aerc/models"
)
func genFakeTree() *Thread {
- tree := &Thread{
- Uid: 0,
- }
+ tree := new(Thread)
var prevChild *Thread
- for i := 1; i < 3; i++ {
+ for i := uint32(1); i < uint32(3); i++ {
child := &Thread{
- Uid: uint32(i * 10),
+ Uid: models.Uint32ToUid(i * 10),
Parent: tree,
PrevSibling: prevChild,
}
@@ -26,9 +26,9 @@ func genFakeTree() *Thread {
}
prevChild = child
var prevSecond *Thread
- for j := 1; j < 3; j++ {
+ for j := uint32(1); j < uint32(3); j++ {
second := &Thread{
- Uid: child.Uid + uint32(j),
+ Uid: models.Uint32ToUid(models.UidToUint32(child.Uid) + j),
Parent: child,
PrevSibling: prevSecond,
}
@@ -41,13 +41,13 @@ func genFakeTree() *Thread {
}
prevSecond = second
var prevThird *Thread
- limit := 3
+ limit := uint32(3)
if j == 2 {
limit = 8
}
- for k := 1; k < limit; k++ {
+ for k := uint32(1); k < limit; k++ {
third := &Thread{
- Uid: second.Uid*10 + uint32(k),
+ Uid: models.Uint32ToUid(models.UidToUint32(second.Uid)*10 + j),
Parent: second,
PrevSibling: prevThird,
}
@@ -107,7 +107,7 @@ func TestNewWalk(t *testing.T) {
func uidSeq(tree *Thread) string {
var seq []string
tree.Walk(func(t *Thread, _ int, _ error) error {
- seq = append(seq, fmt.Sprintf("%d", t.Uid))
+ seq = append(seq, string(t.Uid))
return nil
})
return strings.Join(seq, ".")
@@ -116,25 +116,25 @@ func uidSeq(tree *Thread) string {
func TestThread_AddChild(t *testing.T) {
tests := []struct {
name string
- seq []int
+ seq []models.UID
want string
}{
{
name: "ascending",
- seq: []int{1, 2, 3, 4, 5, 6},
- want: "0.1.2.3.4.5.6",
+ seq: []models.UID{"1", "2", "3", "4", "5", "6"},
+ want: ".1.2.3.4.5.6",
},
{
name: "descending",
- seq: []int{6, 5, 4, 3, 2, 1},
- want: "0.6.5.4.3.2.1",
+ seq: []models.UID{"6", "5", "4", "3", "2", "1"},
+ want: ".6.5.4.3.2.1",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
- tree := &Thread{Uid: 0}
+ tree := new(Thread)
for _, i := range test.seq {
- tree.AddChild(&Thread{Uid: uint32(i)})
+ tree.AddChild(&Thread{Uid: i})
}
if got := uidSeq(tree); got != test.want {
t.Errorf("got: %s, but wanted: %s", got,
@@ -147,30 +147,30 @@ func TestThread_AddChild(t *testing.T) {
func TestThread_OrderedInsert(t *testing.T) {
tests := []struct {
name string
- seq []int
+ seq []models.UID
want string
}{
{
name: "ascending",
- seq: []int{1, 2, 3, 4, 5, 6},
- want: "0.1.2.3.4.5.6",
+ seq: []models.UID{"1", "2", "3", "4", "5", "6"},
+ want: ".1.2.3.4.5.6",
},
{
name: "descending",
- seq: []int{6, 5, 4, 3, 2, 1},
- want: "0.1.2.3.4.5.6",
+ seq: []models.UID{"6", "5", "4", "3", "2", "1"},
+ want: ".1.2.3.4.5.6",
},
{
name: "mixed",
- seq: []int{2, 1, 6, 3, 4, 5},
- want: "0.1.2.3.4.5.6",
+ seq: []models.UID{"2", "1", "6", "3", "4", "5"},
+ want: ".1.2.3.4.5.6",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
- tree := &Thread{Uid: 0}
+ tree := new(Thread)
for _, i := range test.seq {
- tree.OrderedInsert(&Thread{Uid: uint32(i)})
+ tree.OrderedInsert(&Thread{Uid: i})
}
if got := uidSeq(tree); got != test.want {
t.Errorf("got: %s, but wanted: %s", got,
@@ -183,32 +183,32 @@ func TestThread_OrderedInsert(t *testing.T) {
func TestThread_InsertCmd(t *testing.T) {
tests := []struct {
name string
- seq []int
+ seq []models.UID
want string
}{
{
name: "ascending",
- seq: []int{1, 2, 3, 4, 5, 6},
- want: "0.6.4.2.1.3.5",
+ seq: []models.UID{"1", "2", "3", "4", "5", "6"},
+ want: ".6.4.2.1.3.5",
},
{
name: "descending",
- seq: []int{6, 5, 4, 3, 2, 1},
- want: "0.6.4.2.1.3.5",
+ seq: []models.UID{"6", "5", "4", "3", "2", "1"},
+ want: ".6.4.2.1.3.5",
},
{
name: "mixed",
- seq: []int{2, 1, 6, 3, 4, 5},
- want: "0.6.4.2.1.3.5",
+ seq: []models.UID{"2", "1", "6", "3", "4", "5"},
+ want: ".6.4.2.1.3.5",
},
}
- sortMap := map[uint32]int{
- uint32(6): 1,
- uint32(4): 2,
- uint32(2): 3,
- uint32(1): 4,
- uint32(3): 5,
- uint32(5): 6,
+ sortMap := map[models.UID]int{
+ "6": 1,
+ "4": 2,
+ "2": 3,
+ "1": 4,
+ "3": 5,
+ "5": 6,
}
// bigger compares the new child with the next node and returns true if
@@ -219,9 +219,9 @@ func TestThread_InsertCmd(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
- tree := &Thread{Uid: 0}
+ tree := new(Thread)
for _, i := range test.seq {
- tree.InsertCmp(&Thread{Uid: uint32(i)}, bigger)
+ tree.InsertCmp(&Thread{Uid: i}, bigger)
}
if got := uidSeq(tree); got != test.want {
t.Errorf("got: %s, but wanted: %s", got,