/* Return the number of files matching the query, or -1 for an error */ static int count_files (notmuch_query_t *query) { notmuch_messages_t *messages; notmuch_message_t *message; notmuch_filenames_t *filenames; notmuch_status_t status; int count = 0; status = notmuch_query_search_messages_st (query, &messages); if (print_status_query ("notmuch count", query, status)) return -1; for (; notmuch_messages_valid (messages); notmuch_messages_move_to_next (messages)) { message = notmuch_messages_get (messages); filenames = notmuch_message_get_filenames (message); for (; notmuch_filenames_valid (filenames); notmuch_filenames_move_to_next (filenames)) count++; notmuch_filenames_destroy (filenames); notmuch_message_destroy (message); } notmuch_messages_destroy (messages); return count; }
static int remove_filename(struct nm_ctxdata *data, const char *path) { notmuch_status_t st; notmuch_filenames_t *ls; notmuch_message_t *msg = NULL; notmuch_database_t *db = get_db(data, TRUE); int trans; dprint(2, (debugfile, "nm: remove filename '%s'\n", path)); if (!db) return -1; st = notmuch_database_find_message_by_filename(db, path, &msg); if (st || !msg) return -1; trans = db_trans_begin(data); if (trans < 0) return -1; /* * note that unlink() is probably unnecessary here, it's already removed * by mh_sync_mailbox_message(), but for sure... */ st = notmuch_database_remove_message(db, path); switch (st) { case NOTMUCH_STATUS_SUCCESS: dprint(2, (debugfile, "nm: remove success, call unlink\n")); unlink(path); break; case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID: dprint(2, (debugfile, "nm: remove succes (duplicate), call unlink\n")); unlink(path); for (ls = notmuch_message_get_filenames(msg); ls && notmuch_filenames_valid(ls); notmuch_filenames_move_to_next(ls)) { path = notmuch_filenames_get(ls); dprint(2, (debugfile, "nm: remove duplicate: '%s'\n", path)); unlink(path); notmuch_database_remove_message(db, path); } break; default: dprint(1, (debugfile, "nm: failed to remove '%s' [st=%d]\n", path, (int) st)); break; } notmuch_message_destroy(msg); if (trans) db_trans_end(data); return 0; }
static const char *get_message_last_filename(notmuch_message_t *msg) { notmuch_filenames_t *ls; const char *name = NULL; for (ls = notmuch_message_get_filenames(msg); ls && notmuch_filenames_valid(ls); notmuch_filenames_move_to_next(ls)) { name = notmuch_filenames_get(ls); } return name; }
static int _count_filenames (notmuch_message_t *message) { notmuch_filenames_t *filenames; int i = 0; filenames = notmuch_message_get_filenames (message); while (notmuch_filenames_valid (filenames)) { notmuch_filenames_move_to_next (filenames); i++; } notmuch_filenames_destroy (filenames); return i; }
static int msg_filenames(Tcl_Interp *interp, notmuch_message_t *msg, int argc, const char *argv[]) { if (argc != 0) { tcl_result_printf(interp, "msg filenames takes no arguments"); return TCL_ERROR; } Tcl_Obj* list = Tcl_NewListObj(0, NULL); if (!list) { return TCL_ERROR; } notmuch_filenames_t *fns = notmuch_message_get_filenames(msg); while (notmuch_filenames_valid(fns)) { const char *fn = notmuch_filenames_get(fns); Tcl_ListObjAppendElement(interp, list, Tcl_NewStringObj(fn, -1)); notmuch_filenames_move_to_next(fns); } notmuch_filenames_destroy(fns); Tcl_SetObjResult(interp, list); return TCL_OK; }
int cmd_move_message(ClientData data, Tcl_Interp *interp, int argc, const char *argv[]) { filter_context_t *ctx = FILTER_CONTEXT(data); notmuch_message_t *msg = ctx->current_message; notmuch_status_t nmrc; if (argc != 2) { tcl_result_printf(interp, "wrong # of args: got %d, expected move folder", argc); return TCL_ERROR; } const char *folder = argv[1]; if (folder[0] == '/') { tcl_result_printf(interp, "invalid folder '%s'", folder); return TCL_ERROR; } log_debug("moving message %s to folder %s", notmuch_message_get_message_id(msg), folder); char *folder_path = g_strdup_printf("%s/%s", notmuch_database_get_path(ctx->database), folder); int status = TCL_ERROR; notmuch_filenames_t *fns = notmuch_message_get_filenames(msg); int nmoved = 0; while (notmuch_filenames_valid(fns)) { const char *fn = notmuch_filenames_get(fns); char *new_fn = NULL; if (g_str_has_prefix(fn, folder_path)) { log_debug("file %s already in folder %s", fn, folder); } else if (ctx->dry_run) { log_debug("moving %s to folder %s", fn, folder); } else { log_debug("moving %s to folder %s", fn, folder); int rc = maildir_deliver_link(fn, folder_path, &new_fn); if (rc) { tcl_result_printf(interp, "delivery error: %s", strerror(errno)); goto done; } log_debug("delivered as %s", new_fn); nmrc = notmuch_database_add_message(ctx->database, new_fn, NULL); switch (nmrc) { case NOTMUCH_STATUS_SUCCESS: log_warning("%s: message was not in database", new_fn); case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID: log_debug("added new file to database"); break; default: tcl_result_printf(interp, "error adding %s to database: %s", new_fn, notmuch_status_to_string(nmrc)); goto done; } nmrc = notmuch_database_remove_message(ctx->database, fn); switch (nmrc) { case NOTMUCH_STATUS_SUCCESS: log_warning("%s: file was only file for message", fn); case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID: log_debug("removed file %s from database", fn); break; default: tcl_result_printf(interp, "error removing %s from database: %s", fn, notmuch_status_to_string(nmrc)); goto done; } if (unlink(fn)) { tcl_result_printf(interp, "error unlinking %s: %s", fn, strerror(errno)); goto done; } nmoved += 1; } notmuch_filenames_move_to_next(fns); } notmuch_filenames_destroy(fns); fns = NULL; if (nmoved == 0) { Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); status = TCL_OK; goto done; } log_debug("syncing maildir flags"); const char *mid = notmuch_message_get_message_id(msg); nmrc = notmuch_database_find_message(ctx->database, mid, &msg); if (nmrc != NOTMUCH_STATUS_SUCCESS) { tcl_result_printf(interp, "cannot re-find message %s", mid); goto done; } notmuch_message_destroy(ctx->current_message); ctx->current_message = msg; nmrc = notmuch_message_tags_to_maildir_flags(msg); if (nmrc != NOTMUCH_STATUS_SUCCESS) { tcl_result_printf(interp, "error syncing tags back to flags"); goto done; } Tcl_SetObjResult(interp, Tcl_NewIntObj(nmoved)); status = TCL_OK; done: if (fns) { notmuch_filenames_destroy(fns); } g_free(folder_path); return status; }
static int do_search_messages (search_context_t *ctx) { notmuch_message_t *message; notmuch_messages_t *messages; notmuch_filenames_t *filenames; sprinter_t *format = ctx->format; int i; notmuch_status_t status; if (ctx->offset < 0) { unsigned count; notmuch_status_t status; status = notmuch_query_count_messages_st (ctx->query, &count); if (print_status_query ("notmuch search", ctx->query, status)) return 1; ctx->offset += count; if (ctx->offset < 0) ctx->offset = 0; } status = notmuch_query_search_messages_st (ctx->query, &messages); if (print_status_query ("notmuch search", ctx->query, status)) return 1; format->begin_list (format); for (i = 0; notmuch_messages_valid (messages) && (ctx->limit < 0 || i < ctx->offset + ctx->limit); notmuch_messages_move_to_next (messages), i++) { if (i < ctx->offset) continue; message = notmuch_messages_get (messages); if (ctx->output == OUTPUT_FILES) { int j; filenames = notmuch_message_get_filenames (message); for (j = 1; notmuch_filenames_valid (filenames); notmuch_filenames_move_to_next (filenames), j++) { if (ctx->dupe < 0 || ctx->dupe == j) { format->string (format, notmuch_filenames_get (filenames)); format->separator (format); } } notmuch_filenames_destroy( filenames ); } else if (ctx->output == OUTPUT_MESSAGES) { /* special case 1 for speed */ if (ctx->dupe <= 1 || ctx->dupe <= _count_filenames (message)) { format->set_prefix (format, "id"); format->string (format, notmuch_message_get_message_id (message)); format->separator (format); } } else { if (ctx->output & OUTPUT_SENDER) { const char *addrs; addrs = notmuch_message_get_header (message, "from"); process_address_header (ctx, addrs); } if (ctx->output & OUTPUT_RECIPIENTS) { const char *hdrs[] = { "to", "cc", "bcc" }; const char *addrs; size_t j; for (j = 0; j < ARRAY_SIZE (hdrs); j++) { addrs = notmuch_message_get_header (message, hdrs[j]); process_address_header (ctx, addrs); } } } notmuch_message_destroy (message); } if (ctx->addresses && (ctx->output & OUTPUT_COUNT || ctx->dedup == DEDUP_ADDRESS)) g_hash_table_foreach (ctx->addresses, print_hash_value, ctx); notmuch_messages_destroy (messages); format->end (format); return 0; }
static int do_search_messages (const search_format_t *format, notmuch_query_t *query, output_t output, int offset, int limit) { notmuch_message_t *message; notmuch_messages_t *messages; notmuch_filenames_t *filenames; int first_message = 1; int i; if (offset < 0) { offset += notmuch_query_count_messages (query); if (offset < 0) offset = 0; } messages = notmuch_query_search_messages (query); if (messages == NULL) return 1; fputs (format->results_start, stdout); for (i = 0; notmuch_messages_valid (messages) && (limit < 0 || i < offset + limit); notmuch_messages_move_to_next (messages), i++) { if (i < offset) continue; message = notmuch_messages_get (messages); if (output == OUTPUT_FILES) { filenames = notmuch_message_get_filenames (message); for (; notmuch_filenames_valid (filenames); notmuch_filenames_move_to_next (filenames)) { if (! first_message) fputs (format->item_sep, stdout); format->item_id (message, "", notmuch_filenames_get (filenames)); first_message = 0; } notmuch_filenames_destroy( filenames ); } else { /* output == OUTPUT_MESSAGES */ if (! first_message) fputs (format->item_sep, stdout); format->item_id (message, "id:", notmuch_message_get_message_id (message)); first_message = 0; } notmuch_message_destroy (message); } notmuch_messages_destroy (messages); if (first_message) fputs (format->results_null, stdout); else fputs (format->results_end, stdout); return 0; }