+/* Tag messages matching 'query_string' according to 'tag_ops', which
+ * must be an array of tagging operations terminated with an empty
+ * element. */
+static int
+tag_query (void *ctx, notmuch_database_t *notmuch, const char *query_string,
+ tag_operation_t *tag_ops, notmuch_bool_t synchronize_flags)
+{
+ notmuch_query_t *query;
+ notmuch_messages_t *messages;
+ notmuch_message_t *message;
+ int i;
+
+ /* 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;
+ }
+
+ 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);
+
+ notmuch_message_freeze (message);
+
+ for (i = 0; tag_ops[i].tag; i++) {
+ if (tag_ops[i].remove)
+ notmuch_message_remove_tag (message, tag_ops[i].tag);
+ else
+ notmuch_message_add_tag (message, tag_ops[i].tag);
+ }
+
+ notmuch_message_thaw (message);
+
+ if (synchronize_flags)
+ notmuch_message_tags_to_maildir_flags (message);
+
+ notmuch_message_destroy (message);
+ }
+
+ notmuch_query_destroy (query);
+
+ return interrupted;
+}
+