Ejemplo n.º 1
0
/* Non-zero return indicates an error in retrieving the message,
 * or in applying the tags.  Missing messages are reported, but not
 * considered errors.
 */
static int
tag_message (unused (void *ctx),
	     notmuch_database_t *notmuch,
	     const char *message_id,
	     tag_op_list_t *tag_ops,
	     tag_op_flag_t flags)
{
    notmuch_status_t status;
    notmuch_message_t *message = NULL;
    int ret = 0;

    status = notmuch_database_find_message (notmuch, message_id, &message);
    if (status) {
	fprintf (stderr, "Error applying tags to message %s: %s\n",
		 message_id, notmuch_status_to_string (status));
	return 1;
    }
    if (message == NULL) {
	fprintf (stderr, "Warning: cannot apply tags to missing message: %s\n",
		 message_id);
	/* We consider this a non-fatal error. */
	return 0;
    }

    /* In order to detect missing messages, this check/optimization is
     * intentionally done *after* first finding the message. */
    if ((flags & TAG_FLAG_REMOVE_ALL) || tag_op_list_size (tag_ops))
	ret = tag_op_list_apply (message, tag_ops, flags);

    notmuch_message_destroy (message);

    return ret;
}
Ejemplo n.º 2
0
/* Tag messages matching 'query_string' according to 'tag_ops'
 */
static int
tag_query (void *ctx, notmuch_database_t *notmuch, const char *query_string,
	   tag_op_list_t *tag_ops, tag_op_flag_t flags)
{
    notmuch_query_t *query;
    notmuch_messages_t *messages;
    notmuch_message_t *message;
    int ret = NOTMUCH_STATUS_SUCCESS;

    if (! (flags & TAG_FLAG_REMOVE_ALL)) {
	/* Optimize the query so it excludes messages that already
	 * have the specified set of tags. */
	query_string = _optimize_tag_query (ctx, query_string, tag_ops);
	if (query_string == NULL) {
	    fprintf (stderr, "Out of memory.\n");
	    return 1;
	}
	flags |= TAG_FLAG_PRE_OPTIMIZED;
    }

    query = notmuch_query_create (notmuch, query_string);
    if (query == NULL) {
	fprintf (stderr, "Out of memory.\n");
	return 1;
    }

    /* tagging is not interested in any special sort order */
    notmuch_query_set_sort (query, NOTMUCH_SORT_UNSORTED);

    for (messages = notmuch_query_search_messages (query);
	 notmuch_messages_valid (messages) && ! interrupted;
	 notmuch_messages_move_to_next (messages)) {
	message = notmuch_messages_get (messages);
	ret = tag_op_list_apply (message, tag_ops, flags);
	notmuch_message_destroy (message);
	if (ret != NOTMUCH_STATUS_SUCCESS)
	    break;
    }

    notmuch_query_destroy (query);

    return ret || interrupted;
}
Ejemplo n.º 3
0
/* Add the specified message file to the notmuch database, applying tags.
 * The file is renamed to encode notmuch tags as maildir flags. */
static void
add_file_to_database (notmuch_database_t *notmuch, const char *path,
		      tag_op_list_t *tag_ops)
{
    notmuch_message_t *message;
    notmuch_status_t status;

    status = notmuch_database_add_message (notmuch, path, &message);
    switch (status) {
    case NOTMUCH_STATUS_SUCCESS:
    case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:
	break;
    default:
    case NOTMUCH_STATUS_FILE_NOT_EMAIL:
    case NOTMUCH_STATUS_READ_ONLY_DATABASE:
    case NOTMUCH_STATUS_XAPIAN_EXCEPTION:
    case NOTMUCH_STATUS_OUT_OF_MEMORY:
    case NOTMUCH_STATUS_FILE_ERROR:
    case NOTMUCH_STATUS_NULL_POINTER:
    case NOTMUCH_STATUS_TAG_TOO_LONG:
    case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:
    case NOTMUCH_STATUS_UNBALANCED_ATOMIC:
    case NOTMUCH_STATUS_LAST_STATUS:
	fprintf (stderr, "Error: failed to add `%s' to notmuch database: %s\n",
		 path, notmuch_status_to_string (status));
	return;
    }

    if (status == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) {
	/* Don't change tags of an existing message. */
	status = notmuch_message_tags_to_maildir_flags (message);
	if (status != NOTMUCH_STATUS_SUCCESS)
	    fprintf (stderr, "Error: failed to sync tags to maildir flags\n");
    } else {
	tag_op_list_apply (message, tag_ops, TAG_FLAG_MAILDIR_SYNC);
    }

    notmuch_message_destroy (message);
}
Ejemplo n.º 4
0
/*
 * Add the specified message file to the notmuch database, applying
 * tags in tag_ops. If synchronize_flags is TRUE, the tags are
 * synchronized to maildir flags (which may result in message file
 * rename).
 *
 * Return NOTMUCH_STATUS_SUCCESS on success, errors otherwise. If keep
 * is TRUE, errors in tag changes and flag syncing are ignored and
 * success status is returned; otherwise such errors cause the message
 * to be removed from the database. Failure to add the message to the
 * database results in error status regardless of keep.
 */
static notmuch_status_t
add_file (notmuch_database_t *notmuch, const char *path, tag_op_list_t *tag_ops,
	  notmuch_bool_t synchronize_flags, notmuch_bool_t keep)
{
    notmuch_message_t *message;
    notmuch_status_t status;

    status = notmuch_database_add_message (notmuch, path, &message);
    if (status == NOTMUCH_STATUS_SUCCESS) {
	status = tag_op_list_apply (message, tag_ops, 0);
	if (status) {
	    fprintf (stderr, "%s: failed to apply tags to file '%s': %s\n",
		     keep ? "Warning" : "Error",
		     path, notmuch_status_to_string (status));
	    goto DONE;
	}
    } else if (status == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) {
	status = NOTMUCH_STATUS_SUCCESS;
    } else if (status == NOTMUCH_STATUS_FILE_NOT_EMAIL) {
	fprintf (stderr, "Error: delivery of non-mail file: '%s'\n", path);
	goto FAIL;
    } else {
	fprintf (stderr, "Error: failed to add '%s' to notmuch database: %s\n",
		 path, notmuch_status_to_string (status));
	goto FAIL;
    }

    if (synchronize_flags) {
	status = notmuch_message_tags_to_maildir_flags (message);
	if (status != NOTMUCH_STATUS_SUCCESS)
	    fprintf (stderr, "%s: failed to sync tags to maildir flags for '%s': %s\n",
		     keep ? "Warning" : "Error",
		     path, notmuch_status_to_string (status));

	/*
	 * Note: Unfortunately a failed maildir flag sync might
	 * already have renamed the file, in which case the cleanup
	 * path may fail.
	 */
    }

  DONE:
    notmuch_message_destroy (message);

    if (status) {
	if (keep) {
	    status = NOTMUCH_STATUS_SUCCESS;
	} else {
	    notmuch_status_t cleanup_status;

	    cleanup_status = notmuch_database_remove_message (notmuch, path);
	    if (cleanup_status != NOTMUCH_STATUS_SUCCESS &&
		cleanup_status != NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) {
		fprintf (stderr, "Warning: failed to remove '%s' from database "
			 "after errors: %s. Please run 'notmuch new' to fix.\n",
			 path, notmuch_status_to_string (cleanup_status));
	    }
	}
    }

  FAIL:
    return status;
}