--- /dev/null
+Return-Path: <dkg@fifthhorseman.net>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by arlo.cworth.org (Postfix) with ESMTP id 6BBE16DE092F\r
+ for <notmuch@notmuchmail.org>; Fri, 8 Jul 2016 03:13:24 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at cworth.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 0.538\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=0.538 tagged_above=-999 required=5 tests=[AWL=-0.538,\r
+ DATE_IN_PAST_03_06=1.076] autolearn=disabled\r
+Received: from arlo.cworth.org ([127.0.0.1])\r
+ by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id ePRrZ0gv-n_5 for <notmuch@notmuchmail.org>;\r
+ Fri, 8 Jul 2016 03:13:16 -0700 (PDT)\r
+Received: from che.mayfirst.org (che.mayfirst.org [162.247.75.118])\r
+ by arlo.cworth.org (Postfix) with ESMTP id 0FB1C6DE015B\r
+ for <notmuch@notmuchmail.org>; Fri, 8 Jul 2016 03:13:07 -0700 (PDT)\r
+Received: from fifthhorseman.net (unknown [88.128.80.54])\r
+ by che.mayfirst.org (Postfix) with ESMTPSA id 94D94F993\r
+ for <notmuch@notmuchmail.org>; Fri, 8 Jul 2016 06:13:03 -0400 (EDT)\r
+Received: by fifthhorseman.net (Postfix, from userid 1000)\r
+ id CF6DB20887; Fri, 8 Jul 2016 00:36:50 -0400 (EDT)\r
+From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>\r
+To: Notmuch Mail <notmuch@notmuchmail.org>\r
+Subject: [PATCH] n_m_remove_property(msg, key,\r
+ NULL) should removes all properties with key\r
+Date: Fri, 8 Jul 2016 06:36:50 +0200\r
+Message-Id: <1467952610-27015-1-git-send-email-dkg@fifthhorseman.net>\r
+X-Mailer: git-send-email 2.8.1\r
+In-Reply-To: <1465779955-5539-4-git-send-email-david@tethera.net>\r
+References: <1465779955-5539-4-git-send-email-david@tethera.net>\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.20\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <https://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch/>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <https://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Fri, 08 Jul 2016 10:13:24 -0000\r
+\r
+We should not require value to be non-NULL when there is a perfectly\r
+sensible semantic:\r
+\r
+ notmuch_message_remove_property(msg, key, NULL)\r
+\r
+should mean "remove all properties with the given key from msg"\r
+---\r
+ lib/message-property.cc | 28 ++++++++++++++++++++--------\r
+ lib/notmuch.h | 5 +++--\r
+ 2 files changed, 23 insertions(+), 10 deletions(-)\r
+\r
+This should apply on top of bremner's "properties" series, making the\r
+semantics slightly more useful.\r
+\r
+diff --git a/lib/message-property.cc b/lib/message-property.cc\r
+index 4fa6cac..338f3fb 100644\r
+--- a/lib/message-property.cc\r
++++ b/lib/message-property.cc\r
+@@ -48,22 +48,34 @@ _notmuch_message_modify_property (notmuch_message_t *message, const char *key, c\r
+ if (status)\r
+ return status;\r
+ \r
+- if (key == NULL || value == NULL)\r
++ if (key == NULL)\r
+ return NOTMUCH_STATUS_NULL_POINTER;\r
+ \r
+ if (index (key, '='))\r
+ return NOTMUCH_STATUS_ILLEGAL_ARGUMENT;\r
+ \r
+- term = talloc_asprintf (message, "%s=%s", key, value);\r
++ if (value == NULL)\r
++ {\r
++ if (!delete_it)\r
++ return NOTMUCH_STATUS_NULL_POINTER;\r
+ \r
+- if (delete_it)\r
+- private_status = _notmuch_message_remove_term (message, "property", term);\r
++ term = talloc_asprintf (message, "%s%s=", _find_prefix ("property"), key);\r
++ _notmuch_message_remove_terms (message, term);\r
++ }\r
+ else\r
+- private_status = _notmuch_message_add_term (message, "property", term);\r
++ {\r
++ term = talloc_asprintf (message, "%s=%s", key, value);\r
++\r
++ if (delete_it)\r
++ private_status = _notmuch_message_remove_term (message, "property", term);\r
++ else\r
++ private_status = _notmuch_message_add_term (message, "property", term);\r
++\r
++ if (private_status)\r
++ return COERCE_STATUS (private_status,\r
++ "Unhandled error modifying message property");\r
++ }\r
+ \r
+- if (private_status)\r
+- return COERCE_STATUS (private_status,\r
+- "Unhandled error modifying message property");\r
+ if (! _notmuch_message_frozen (message))\r
+ _notmuch_message_sync (message);\r
+ \r
+diff --git a/lib/notmuch.h b/lib/notmuch.h\r
+index f6bad67..0d667f5 100644\r
+--- a/lib/notmuch.h\r
++++ b/lib/notmuch.h\r
+@@ -1698,11 +1698,12 @@ notmuch_message_add_property (notmuch_message_t *message, const char *key, const\r
+ /**\r
+ * Remove a (key,value) pair from a message.\r
+ *\r
+- * It is not an error to remove a non-existant (key,value) pair\r
++ * It is not an error to remove a non-existant (key,value) pair. If\r
++ * *value* is NULL, remove all properties with the given key.\r
+ *\r
+ * @returns\r
+ * - NOTMUCH_STATUS_ILLEGAL_ARGUMENT: *key* may not contain an '=' character.\r
+- * - NOTMUCH_STATUS_NULL_POINTER: Neither *key* nor *value* may be NULL.\r
++ * - NOTMUCH_STATUS_NULL_POINTER: *key* may not be NULL.\r
+ * - NOTMUCH_STATUS_SUCCESS: No error occured.\r
+ */\r
+ notmuch_status_t\r
+-- \r
+2.8.1\r
+\r