Copy only fields whose caching decision is not "no" in the destination mailbox.
mail_index_update_ext(ctx->ctx.trans, ctx->ctx.seq,
ctx->mbox->guid_ext_id, data, NULL);
}
+ index_copy_cache_fields(_ctx, mail, ctx->ctx.seq);
save_mail = array_append_space(&ctx->mails);
save_mail->seq = ctx->ctx.seq;
}
dbox_save_add_to_index(ctx);
+ index_copy_cache_fields(_ctx, mail, ctx->seq);
+
sdbox_save_add_file(_ctx, dest_file);
if (_ctx->dest_mail != NULL) {
mail_set_seq(_ctx->dest_mail, ctx->seq);
i_free_and_null(ctx->pop3_uidl);
index_attachment_save_free(ctx);
}
+
+static void
+mail_copy_cache_field(struct mail_save_context *ctx, struct mail *src_mail,
+ uint32_t dest_seq, const char *name, buffer_t *buf)
+{
+ struct mailbox_transaction_context *dest_trans = ctx->transaction;
+ struct index_transaction_context *dest_itrans =
+ (struct index_transaction_context *)dest_trans;
+ struct index_transaction_context *src_itrans =
+ (struct index_transaction_context *)src_mail->transaction;
+ const struct mail_cache_field *dest_field;
+ unsigned int src_field_idx, dest_field_idx;
+
+ src_field_idx = mail_cache_register_lookup(src_mail->box->cache, name);
+ i_assert(src_field_idx != -1U);
+
+ dest_field_idx = mail_cache_register_lookup(dest_trans->box->cache, name);
+ if (dest_field_idx == -1U) {
+ /* unknown field */
+ return;
+ }
+ dest_field = mail_cache_register_get_field(dest_trans->box->cache,
+ dest_field_idx);
+ if ((dest_field->decision &
+ ~MAIL_CACHE_DECISION_FORCED) == MAIL_CACHE_DECISION_NO) {
+ /* field not wanted in destination mailbox */
+ return;
+ }
+
+ buffer_set_used_size(buf, 0);
+ if (mail_cache_lookup_field(src_itrans->cache_view, buf,
+ src_mail->seq, src_field_idx) > 0) {
+ mail_cache_add(dest_itrans->cache_trans, dest_seq,
+ dest_field_idx, buf->data, buf->used);
+ }
+}
+
+void index_copy_cache_fields(struct mail_save_context *ctx,
+ struct mail *src_mail, uint32_t dest_seq)
+{
+ T_BEGIN {
+ struct mailbox_status src_status;
+ const char *const *namep;
+ buffer_t *buf;
+
+ index_storage_get_status(src_mail->box, STATUS_CACHE_FIELDS,
+ &src_status);
+
+ buf = buffer_create_dynamic(pool_datastack_create(), 1024);
+ array_foreach(src_status.cache_fields, namep) {
+ mail_copy_cache_field(ctx, src_mail, dest_seq,
+ *namep, buf);
+ }
+ } T_END;
+}
struct mail_transaction_commit_changes *changes_r);
void index_transaction_rollback(struct mailbox_transaction_context *t);
void index_save_context_free(struct mail_save_context *ctx);
+void index_copy_cache_fields(struct mail_save_context *ctx,
+ struct mail *src_mail, uint32_t dest_seq);
bool index_keyword_array_cmp(const ARRAY_TYPE(keyword_indexes) *k1,
const ARRAY_TYPE(keyword_indexes) *k2);
}
/* hardlinked to tmp/, treat as normal copied mail */
- mf = maildir_save_add(ctx, dest_fname);
+ mf = maildir_save_add(ctx, dest_fname, mail);
if (mail_get_special(mail, MAIL_FETCH_GUID, &guid) == 0) {
if (*guid != '\0')
maildir_save_set_dest_basename(ctx, mf, guid);
}
struct maildir_filename *
-maildir_save_add(struct mail_save_context *_ctx, const char *tmp_fname)
+maildir_save_add(struct mail_save_context *_ctx, const char *tmp_fname,
+ struct mail *src_mail)
{
struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx;
struct maildir_filename *mf;
_ctx->dest_mail->saving = TRUE;
if (ctx->input == NULL) {
- /* FIXME: copying with hardlinking. we could copy the
- cached data directly */
+ /* copying with hardlinking. */
+ i_assert(src_mail != NULL);
+ index_copy_cache_fields(_ctx, src_mail, ctx->seq);
ctx->cur_dest_mail = NULL;
} else {
input = index_mail_cache_parse_init(_ctx->dest_mail,
ctx->input = i_stream_create_crlf(input);
else
ctx->input = i_stream_create_lf(input);
- mf = maildir_save_add(_ctx, fname);
+ mf = maildir_save_add(_ctx, fname, NULL);
if (_ctx->guid != NULL) {
maildir_save_set_dest_basename(_ctx, mf,
_ctx->guid);
void maildir_save_cancel(struct mail_save_context *ctx);
struct maildir_filename *
-maildir_save_add(struct mail_save_context *_ctx, const char *tmp_fname);
+maildir_save_add(struct mail_save_context *_ctx, const char *tmp_fname,
+ struct mail *src_mail);
void maildir_save_set_dest_basename(struct mail_save_context *ctx,
struct maildir_filename *mf,
const char *basename);