[PATCH 2/2] lib: add 'safe' setting for flags

Subject: [PATCH 2/2] lib: add 'safe' setting for flags

Date: Sat, 16 Jul 2011 23:56:13 -0400

To: notmuch@notmuchmail.org

Cc: Antoine Beaupré

From: Antoine Beaupré


the 'safe' setting needs to be 'true' for flags to be manipulated by
notmuch new/tag/restore.

for now, only the (T)rash tag is configurable and set to false (by
default) but this could be extended to allow the user to configure which
flags are allowed to be synchronized.

the reason why only T is configurable is because (a) it's the the only
one that is actually dangerous and (b) I couldn't figure out how to
properly configure multiple settings like this.
---
 lib/message.cc    |   40 +++++++++++++++++++++++++---------------
 lib/notmuch.h     |   20 ++++++++++++++++----
 notmuch-new.c     |    1 +
 notmuch-restore.c |    1 +
 notmuch-tag.c     |    1 +
 5 files changed, 44 insertions(+), 19 deletions(-)

diff --git a/lib/message.cc b/lib/message.cc
index f633887..f812648 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -50,16 +50,17 @@ struct maildir_flag_tag {
     char flag;
     const char *tag;
     bool inverse;
+    bool safe;
 };
 
 /* ASCII ordered table of Maildir flags and associated tags */
 static struct maildir_flag_tag flag2tag[] = {
-    { 'D', "draft",   false},
-    { 'F', "flagged", false},
-    { 'P', "passed",  false},
-    { 'R', "replied", false},
-    { 'S', "unread",  true },
-    { 'T', "deleted", false},
+    { 'D', "draft",   false, true},
+    { 'F', "flagged", false, true},
+    { 'P', "passed",  false, true},
+    { 'R', "replied", false, true},
+    { 'S', "unread",  true , true},
+    { 'T', "deleted", false, false},
 };
 
 /* We end up having to call the destructor explicitly because we had
@@ -994,7 +995,6 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message)
     char *combined_flags = talloc_strdup (message, "");
     unsigned i;
     int seen_maildir_info = 0;
-    notmuch_bool_t reckless_trash;
 
     for (filenames = notmuch_message_get_filenames (message);
 	 notmuch_filenames_valid (filenames);
@@ -1022,15 +1022,8 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message)
     if (status)
 	return status;
 
-    // TODO: this should probably be moved up in the stack to avoid
-    // opening the config file on every message (!)
-    config = notmuch_config_open (ctx, NULL, NULL);
-    if (config == NULL)
-	return 1;
-    reckless_trash = notmuch_config_get_maildir_reckless_trash (config);
-
     for (i = 0; i < ARRAY_SIZE(flag2tag); i++) {
-	if (flag2tag[i].flag == 'T' && !reckless_trash) {
+	if (!flag2tag[i].safe) {
 	    continue;
 	}
 	if ((strchr (combined_flags, flag2tag[i].flag) != NULL)
@@ -1119,6 +1112,9 @@ _get_maildir_flag_actions (notmuch_message_t *message,
 	tag = notmuch_tags_get (tags);
 
 	for (i = 0; i < ARRAY_SIZE (flag2tag); i++) {
+	    if (!flag2tag[i].safe) {
+		continue;
+	    }
 	    if (strcmp (tag, flag2tag[i].tag) == 0) {
 		if (flag2tag[i].inverse)
 		    to_clear = talloc_asprintf_append (to_clear,
@@ -1134,6 +1130,9 @@ _get_maildir_flag_actions (notmuch_message_t *message,
 
     /* Then, find the flags for all tags not present. */
     for (i = 0; i < ARRAY_SIZE (flag2tag); i++) {
+	if (!flag2tag[i].safe) {
+	    continue;
+	}
 	if (flag2tag[i].inverse) {
 	    if (strchr (to_clear, flag2tag[i].flag) == NULL)
 		to_set = talloc_asprintf_append (to_set, "%c", flag2tag[i].flag);
@@ -1256,6 +1255,17 @@ _new_maildir_filename (void *ctx,
     return filename_new;
 }
 
+void
+notmuch_message_set_flag_safety (char flag, notmuch_bool_t safe)
+{
+    unsigned i;
+    for (i = 0; i < ARRAY_SIZE (flag2tag); i++) {
+        if (flag2tag[i].flag == flag) {
+            flag2tag[i].safe = safe;
+        }
+    }
+}
+
 notmuch_status_t
 notmuch_message_tags_to_maildir_flags (notmuch_message_t *message)
 {
diff --git a/lib/notmuch.h b/lib/notmuch.h
index f0c1b67..475e75a 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -922,8 +922,7 @@ notmuch_message_remove_all_tags (notmuch_message_t *message);
  *	'P'	Adds the "passed" tag to the message
  *	'R'	Adds the "replied" tag to the message
  *	'S'	Removes the "unread" tag from the message
- * 	'T'	Adds the "deleted" tag to the message and
- *		state->reckless_trash is TRUE.
+ * 	'T'	Adds the "deleted" tag to the message
  *
  * For each flag that is not present, the opposite action (add/remove)
  * is performed for the corresponding tags.
@@ -941,6 +940,9 @@ notmuch_message_remove_all_tags (notmuch_message_t *message);
  * notmuch_database_add_message. See also
  * notmuch_message_tags_to_maildir_flags for synchronizing tag changes
  * back to maildir flags.
+ *
+ * Actions are performed only if the tag is marked as "safe" in the
+ * configuration (only used by maildir_reckless_trash for now).
  */
 notmuch_status_t
 notmuch_message_maildir_flags_to_tags (notmuch_message_t *message);
@@ -964,8 +966,7 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message);
  *   'P' iff the message has the "passed" tag
  *   'R' iff the message has the "replied" tag
  *   'S' iff the message does not have the "unread" tag
- *   'T' iff the message has the "trashed" tag and
- *   state->reckless_trash is TRUE.
+ *   'T' iff the message has the "trashed" tag
  *
  * Any existing flags unmentioned in the list above will be preserved
  * in the renaming.
@@ -979,10 +980,21 @@ notmuch_message_maildir_flags_to_tags (notmuch_message_t *message);
  * notmuch_message_remove_tag, or notmuch_message_freeze/
  * notmuch_message_thaw). See also notmuch_message_maildir_flags_to_tags
  * for synchronizing maildir flag changes back to tags.
+ *
+ * Actions are performed only if the tag is marked as "safe" in the
+ * configuration (only used by maildir_reckless_trash for now).
  */
 notmuch_status_t
 notmuch_message_tags_to_maildir_flags (notmuch_message_t *message);
 
+/* Set the 'safe' setting on the given flag
+ *
+ * The flag is the one-character IMAP flag, for example for Trashed
+ * messages, it's the char 'T'.
+ */
+void
+notmuch_message_set_flag_safety(char flag, notmuch_bool_t safe);
+
 /* Freeze the current state of 'message' within the database.
  *
  * This means that changes to the message state, (via
diff --git a/notmuch-new.c b/notmuch-new.c
index 7d17793..1502a70 100644
--- a/notmuch-new.c
+++ b/notmuch-new.c
@@ -801,6 +801,7 @@ notmuch_new_command (void *ctx, int argc, char *argv[])
 
     add_files_state.new_tags = notmuch_config_get_new_tags (config, &add_files_state.new_tags_length);
     add_files_state.synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config);
+    notmuch_message_set_flag_safety('T', notmuch_config_get_maildir_reckless_trash (config));
     add_files_state.message_ids_to_sync = _filename_list_create (ctx);
     db_path = notmuch_config_get_database_path (config);
 
diff --git a/notmuch-restore.c b/notmuch-restore.c
index f095f64..1f3622e 100644
--- a/notmuch-restore.c
+++ b/notmuch-restore.c
@@ -43,6 +43,7 @@ notmuch_restore_command (unused (void *ctx), int argc, char *argv[])
 	return 1;
 
     synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config);
+    notmuch_message_set_flag_safety('T', notmuch_config_get_maildir_reckless_trash (config));
 
     if (argc) {
 	input = fopen (argv[0], "r");
diff --git a/notmuch-tag.c b/notmuch-tag.c
index 6204ae3..e2f7cb8 100644
--- a/notmuch-tag.c
+++ b/notmuch-tag.c
@@ -101,6 +101,7 @@ notmuch_tag_command (void *ctx, unused (int argc), unused (char *argv[]))
 	return 1;
 
     synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config);
+    notmuch_message_set_flag_safety('T', notmuch_config_get_maildir_reckless_trash (config));
 
     query = notmuch_query_create (notmuch, query_string);
     if (query == NULL) {
-- 
1.7.2.5


Thread: