Mercurial > dovecot > core-2.2
changeset 14616:3a53a2f7927a
imap: Implemented MOVE extension.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 20 Jun 2012 06:21:17 +0300 |
parents | 0a2126680120 |
children | c14c58bedafe |
files | src/imap/cmd-copy.c src/imap/imap-commands.c src/imap/imap-commands.h |
diffstat | 3 files changed, 40 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/cmd-copy.c Wed Jun 20 06:17:40 2012 +0300 +++ b/src/imap/cmd-copy.c Wed Jun 20 06:21:17 2012 +0300 @@ -28,7 +28,7 @@ } } -static int fetch_and_copy(struct client *client, +static int fetch_and_copy(struct client *client, bool move, struct mailbox_transaction_context *t, struct mail_search_args *search_args, const char **src_uidset_r, @@ -62,8 +62,15 @@ save_ctx = mailbox_save_alloc(t); mailbox_save_copy_flags(save_ctx, mail); - if (mailbox_copy(&save_ctx, mail) < 0) - ret = mail->expunged ? 0 : -1; + if (move) { + if (mailbox_move(&save_ctx, mail) < 0) + ret = -1; + } else { + if (mailbox_copy(&save_ctx, mail) < 0) + ret = -1; + } + if (ret < 0 && mail->expunged) + ret = 0; msgset_generator_next(&srcset_ctx, mail->uid); } @@ -72,15 +79,20 @@ if (mailbox_search_deinit(&search_ctx) < 0) ret = -1; - if (mailbox_transaction_commit(&src_trans) < 0) - ret = -1; + if (ret <= 0 && move) { + /* move failed, don't expunge anything */ + mailbox_transaction_rollback(&src_trans); + } else { + if (mailbox_transaction_commit(&src_trans) < 0) + ret = -1; + } *src_uidset_r = str_c(src_uidset); *copy_count_r = copy_count; return ret; } -bool cmd_copy(struct client_command_context *cmd) +static bool cmd_copy_full(struct client_command_context *cmd, bool move) { struct client *client = cmd->client; struct mail_storage *dest_storage; @@ -114,7 +126,8 @@ t = mailbox_transaction_begin(destbox, MAILBOX_TRANSACTION_FLAG_EXTERNAL | MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS); - ret = fetch_and_copy(client, t, search_args, &src_uidset, ©_count); + ret = fetch_and_copy(client, move, t, search_args, + &src_uidset, ©_count); mail_search_args_unref(&search_args); msg = t_str_new(256); @@ -123,11 +136,12 @@ else if (mailbox_transaction_commit_get_changes(&t, &changes) < 0) ret = -1; else if (copy_count == 0) { - str_append(msg, "OK No messages copied."); + str_append(msg, "OK No messages found."); pool_unref(&changes.pool); } else if (seq_range_count(&changes.saved_uids) == 0) { /* not supported by backend (virtual) */ - str_append(msg, "OK Copy completed."); + str_append(msg, move ? "OK Move completed." : + "OK Copy completed."); pool_unref(&changes.pool); } else { i_assert(copy_count == seq_range_count(&changes.saved_uids)); @@ -135,7 +149,10 @@ str_printfa(msg, "OK [COPYUID %u %s ", changes.uid_validity, src_uidset); imap_write_seq_range(msg, &changes.saved_uids); - str_append(msg, "] Copy completed."); + if (move) + str_append(msg, "] Move completed."); + else + str_append(msg, "] Copy completed."); pool_unref(&changes.pool); } @@ -158,3 +175,13 @@ return TRUE; } } + +bool cmd_copy(struct client_command_context *cmd) +{ + return cmd_copy_full(cmd, FALSE); +} + +bool cmd_uid_move(struct client_command_context *cmd) +{ + return cmd_copy_full(cmd, TRUE); +}
--- a/src/imap/imap-commands.c Wed Jun 20 06:17:40 2012 +0300 +++ b/src/imap/imap-commands.c Wed Jun 20 06:21:17 2012 +0300 @@ -56,6 +56,8 @@ { "SORT", cmd_sort, COMMAND_FLAG_USES_SEQS }, { "THREAD", cmd_thread, COMMAND_FLAG_USES_SEQS }, { "UID EXPUNGE", cmd_uid_expunge, COMMAND_FLAG_BREAKS_SEQS }, + { "UID MOVE", cmd_uid_move, COMMAND_FLAG_USES_SEQS | + COMMAND_FLAG_BREAKS_SEQS }, { "UID SORT", cmd_sort, COMMAND_FLAG_BREAKS_SEQS }, { "UID THREAD", cmd_thread, COMMAND_FLAG_BREAKS_SEQS }, { "UNSELECT", cmd_unselect, COMMAND_FLAG_BREAKS_MAILBOX },
--- a/src/imap/imap-commands.h Wed Jun 20 06:17:40 2012 +0300 +++ b/src/imap/imap-commands.h Wed Jun 20 06:21:17 2012 +0300 @@ -110,6 +110,7 @@ bool cmd_sort(struct client_command_context *cmd); bool cmd_thread(struct client_command_context *cmd); bool cmd_uid_expunge(struct client_command_context *cmd); +bool cmd_uid_move(struct client_command_context *cmd); bool cmd_unselect(struct client_command_context *cmd); bool cmd_x_cancel(struct client_command_context *cmd);