If the leaf is successfully rmdir()ed, rmdir() also its parents.
This doesn't work perfectly with if there are multiple levels of \NoSelect
mailboxes. For example with "a/b/c" the listing will already have returned
"a" and "a/b" before it reaches the "a/b/c" code, which will rmdir all of
them, but it's a bit too late at that point. It's too much work to fix
though, and the situation will be fixed on the next list anyway.
}
}
+void mailbox_list_delete_mailbox_until_root(struct mailbox_list *list,
+ const char *storage_name)
+{
+ enum mailbox_list_path_type types[] = {
+ MAILBOX_LIST_PATH_TYPE_DIR,
+ MAILBOX_LIST_PATH_TYPE_ALT_DIR,
+ MAILBOX_LIST_PATH_TYPE_CONTROL,
+ MAILBOX_LIST_PATH_TYPE_INDEX,
+ MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE,
+ };
+ const char *path;
+
+ for (unsigned int i = 0; i < N_ELEMENTS(types); i++) {
+ if (mailbox_list_get_path(list, storage_name, types[i], &path) > 0)
+ mailbox_list_delete_until_root(list, path, types[i]);
+ }
+}
+
static int mailbox_list_try_delete(struct mailbox_list *list, const char *name,
enum mailbox_list_path_type type)
{
}
return -1;
}
-
The root isn't rmdir()ed. */
void mailbox_list_delete_until_root(struct mailbox_list *list, const char *path,
enum mailbox_list_path_type type);
+/* Call mailbox_list_delete_until_root() for all the paths of the mailbox. */
+void mailbox_list_delete_mailbox_until_root(struct mailbox_list *list,
+ const char *storage_name);
/* Wrapper to unlink_directory(UNLINK_DIRECTORY_FLAG_RMDIR). If it fails due
to ELOOP, try to unlink() the path instead. */
int mailbox_list_delete_trash(const char *path, const char **error_r);
#include "mail-storage.h"
#include "mailbox-tree.h"
#include "mailbox-list-subscriptions.h"
+#include "mailbox-list-iter-private.h"
#include "mailbox-list-fs.h"
#include <stdio.h>
doesn't */
return 0;
}
+ if (mailbox_list_iter_try_delete_noselect(&ctx->ctx, &ctx->info, storage_name))
+ return 0;
return 1;
}
#include "imap-match.h"
#include "mail-storage.h"
#include "mailbox-list-subscriptions.h"
+#include "mailbox-list-iter-private.h"
#include "mailbox-list-index.h"
static bool iter_use_index(struct mailbox_list *list,
follow_children = (match & (IMAP_MATCH_YES |
IMAP_MATCH_CHILDREN)) != 0;
if (match == IMAP_MATCH_YES && iter_subscriptions_ok(ctx)) {
- mailbox_list_index_update_next(ctx, TRUE);
- return &ctx->info;
+ /* If this is a) \NoSelect leaf, b) not LAYOUT=index
+ and c) NO-NOSELECT is set, try to rmdir the leaf
+ directores from filesystem. (With LAYOUT=index the
+ \NoSelect mailboxes aren't on the filesystem.) */
+ if (ilist->has_backing_store &&
+ mailbox_list_iter_try_delete_noselect(_ctx, &ctx->info,
+ str_c(ctx->path))) {
+ /* Deleted \NoSelect leaf. Refresh the index
+ later on so it gets removed from the index
+ as well. */
+ mailbox_list_index_refresh_later(_ctx->list);
+ } else {
+ mailbox_list_index_update_next(ctx, TRUE);
+ return &ctx->info;
+ }
} else if ((_ctx->flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0 &&
(ctx->info.flags & MAILBOX_CHILD_SUBSCRIBED) == 0) {
/* listing only subscriptions, but there are no
#ifndef MAILBOX_LIST_ITER_PRIVATE_H
#define MAILBOX_LIST_ITER_PRIVATE_H
+#include "mailbox-list-private.h"
#include "mailbox-list-iter.h"
+#include "mailbox-list-delete.h"
struct autocreate_box {
const char *name;
bool listing_autoboxes:1;
};
+static inline bool
+mailbox_list_iter_try_delete_noselect(struct mailbox_list_iterate_context *ctx,
+ const struct mailbox_info *info,
+ const char *storage_name)
+{
+ if ((info->flags & (MAILBOX_NOSELECT|MAILBOX_NOCHILDREN)) ==
+ (MAILBOX_NOSELECT|MAILBOX_NOCHILDREN) &&
+ ctx->list->set.no_noselect) {
+ /* Try to rmdir() all \NoSelect mailbox leafs and
+ afterwards their parents. */
+ mailbox_list_delete_mailbox_until_root(ctx->list, storage_name);
+ return TRUE;
+ }
+ return FALSE;
+}
+
#endif