about summary refs log tree commit diff
path: root/archive.c
diff options
context:
space:
mode:
Diffstat (limited to 'archive.c')
-rw-r--r--archive.c76
1 files changed, 24 insertions, 52 deletions
diff --git a/archive.c b/archive.c
index 74491a1..20ea5d0 100644
--- a/archive.c
+++ b/archive.c
@@ -80,12 +80,7 @@ static void createDirs(void) {
 	createDir("thread");
 }
 
-static struct Search {
-	size_t cap;
-	size_t len;
-	char **names;
-	char **exprs;
-} search;
+struct Search search;
 
 static void searchAdd(const char *name, const char *expr) {
 	if (search.len == search.cap) {
@@ -134,51 +129,24 @@ static void searchDefault(void) {
 	searchAdd("index", "ALL");
 }
 
-static const char *algo = "REFERENCES";
-
-static void
-searchThreads(struct IMAP *imap, const char *name, const char *expr) {
+static void searchThreads(
+	struct IMAP *imap, struct List threads, const struct Envelope *envelopes,
+	const char *name, const char *expr
+) {
 	struct Resp resp;
-	struct List threads = {0};
-	struct List envelopeItems = {0};
-	struct Envelope *envelopes = NULL;
-
-	enum Atom thread = atom("thread");
-	fprintf(
-		imap->w, "%s UID THREAD %s UTF-8 %s\r\n",
-		Atoms[thread], algo, expr
-	);
-	for (; resp = respOk(imapResp(imap)), resp.tag != thread; respFree(resp)) {
-		if (resp.resp != AtomThread) continue;
-		threads = resp.data;
-		resp.data = (struct List) {0}; // prevent freeing threads with resp
+	struct List roots = {0};
+
+	enum Atom search = atom("search");
+	concatSearch(imap->w, search, threads, expr);
+	for (; resp = respOk(imapResp(imap)), resp.tag != search; respFree(resp)) {
+		if (resp.resp != AtomSearch) continue;
+		roots = resp.data;
+		resp.data = (struct List) {0}; // prevent freeing roots with resp
 	}
 	respFree(resp);
-	if (!threads.len) goto concat;
 
-	enum Atom concat = atom("concat");
-	envelopes = calloc(threads.len, sizeof(*envelopes));
-	if (!envelopes) err(EX_OSERR, "calloc");
-	concatFetch(imap->w, concat, threads);
-	for (; resp = respOk(imapResp(imap)), resp.tag != concat; respFree(resp)) {
-		if (resp.resp != AtomFetch) continue;
-		if (!resp.data.len) errx(EX_PROTOCOL, "missing FETCH data");
-		// Prevent freeing data in envelopes with resp:
-		struct Data items = dataTake(&resp.data.ptr[0]);
-		concatData(threads, envelopes, dataCheck(items, List).list);
-		listPush(&envelopeItems, items);
-	}
-	respFree(resp);
-
-concat:
-	concatSearch(name, threads, envelopes, search.names, search.len);
-
-	for (size_t i = 0; i < threads.len; ++i) {
-		envelopeFree(envelopes[i]);
-	}
-	free(envelopes);
-	listFree(envelopeItems);
-	listFree(threads);
+	concatIndex(name, roots, threads, envelopes);
+	listFree(roots);
 }
 
 int main(int argc, char *argv[]) {
@@ -191,6 +159,7 @@ int main(int argc, char *argv[]) {
 
 	bool idle = false;
 	const char *mailbox = "Archive";
+	const char *algo = "REFERENCES";
 	const char *searchPath = NULL;
 
 	for (
@@ -198,7 +167,7 @@ int main(int argc, char *argv[]) {
 		0 < (opt = getopt(argc, argv, "A:C:H:S:T:a:h:im:p:qs:u:vw:y:"));
 	) {
 		switch (opt) {
-			break; case 'A': concatSearchEntries = strtoul(optarg, NULL, 10);
+			break; case 'A': concatIndexEntries = strtoul(optarg, NULL, 10);
 			break; case 'C': {
 				int error = chdir(optarg);
 				if (error) err(EX_NOINPUT, "%s", optarg);
@@ -362,6 +331,13 @@ concat:;
 	respFree(resp);
 
 	concatThreads(threads, envelopes);
+	for (size_t i = 0; i < search.len; ++i) {
+		searchThreads(
+			&imap, threads, envelopes,
+			search.names[i], search.exprs[i]
+		);
+	}
+
 	for (size_t i = 0; i < threads.len; ++i) {
 		envelopeFree(envelopes[i]);
 	}
@@ -369,10 +345,6 @@ concat:;
 	listFree(envelopeItems);
 	listFree(threads);
 
-	for (size_t i = 0; i < search.len; ++i) {
-		searchThreads(&imap, search.names[i], search.exprs[i]);
-	}
-
 	fflush(stdout);
 	uidWrite("UIDNEXT", uidNext);
 	if (!idle) goto logout;