[PATCH v2 11/11] emacs: Fix search tagging races
authorAustin Clements <amdragon@MIT.EDU>
Thu, 24 Oct 2013 15:19:11 +0000 (11:19 +2000)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:57:36 +0000 (09:57 -0800)
ef/8761481f353d3728c3bd3f7f2b8636277d349e [new file with mode: 0644]

diff --git a/ef/8761481f353d3728c3bd3f7f2b8636277d349e b/ef/8761481f353d3728c3bd3f7f2b8636277d349e
new file mode 100644 (file)
index 0000000..3af1cf6
--- /dev/null
@@ -0,0 +1,218 @@
+Return-Path: <amdragon@mit.edu>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+       by olra.theworths.org (Postfix) with ESMTP id 37F54429E45\r
+       for <notmuch@notmuchmail.org>; Thu, 24 Oct 2013 08:19:50 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.7\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
+       tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+       by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+       with ESMTP id Sa26Z-GJxz2p for <notmuch@notmuchmail.org>;\r
+       Thu, 24 Oct 2013 08:19:43 -0700 (PDT)\r
+Received: from dmz-mailsec-scanner-5.mit.edu (dmz-mailsec-scanner-5.mit.edu\r
+       [18.7.68.34])\r
+       by olra.theworths.org (Postfix) with ESMTP id 323C4429E4E\r
+       for <notmuch@notmuchmail.org>; Thu, 24 Oct 2013 08:19:25 -0700 (PDT)\r
+X-AuditID: 12074422-b7f5a8e000000a34-f4-52693a7cc45b\r
+Received: from mailhub-auth-3.mit.edu ( [18.9.21.43])\r
+       by dmz-mailsec-scanner-5.mit.edu (Symantec Messaging Gateway) with SMTP\r
+       id 6F.56.02612.C7A39625; Thu, 24 Oct 2013 11:19:24 -0400 (EDT)\r
+Received: from outgoing.mit.edu (outgoing-auth-1.mit.edu [18.9.28.11])\r
+       by mailhub-auth-3.mit.edu (8.13.8/8.9.2) with ESMTP id r9OFJJha030444; \r
+       Thu, 24 Oct 2013 11:19:20 -0400\r
+Received: from drake.dyndns.org\r
+       (216-15-114-40.c3-0.arl-ubr1.sbo-arl.ma.cable.rcn.com\r
+       [216.15.114.40]) (authenticated bits=0)\r
+       (User authenticated as amdragon@ATHENA.MIT.EDU)\r
+       by outgoing.mit.edu (8.13.8/8.12.4) with ESMTP id r9OFJDDw012929\r
+       (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT);\r
+       Thu, 24 Oct 2013 11:19:19 -0400\r
+Received: from amthrax by drake.dyndns.org with local (Exim 4.77)\r
+       (envelope-from <amdragon@mit.edu>)\r
+       id 1VZMgq-0006eB-U8; Thu, 24 Oct 2013 11:19:12 -0400\r
+From: Austin Clements <amdragon@MIT.EDU>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH v2 11/11] emacs: Fix search tagging races\r
+Date: Thu, 24 Oct 2013 11:19:11 -0400\r
+Message-Id: <1382627951-25252-12-git-send-email-amdragon@mit.edu>\r
+X-Mailer: git-send-email 1.8.4.rc3\r
+In-Reply-To: <1382627951-25252-1-git-send-email-amdragon@mit.edu>\r
+References: <1382627951-25252-1-git-send-email-amdragon@mit.edu>\r
+X-Brightmail-Tracker:\r
+ H4sIAAAAAAAAA+NgFjrGIsWRmVeSWpSXmKPExsUixCmqrVtjlRlkcOSztkXTdGeL1XN5LK7f\r
+       nMnswOyxc9Zddo9b91+zezxbdYs5gDmKyyYlNSezLLVI3y6BK+PH1GamgouGFdM/trA1MPZr\r
+       djFyckgImEgs3dDKCGGLSVy4t56ti5GLQ0hgH6PEulkP2CGcjYwSVzunMkI4d5gkpr7sYYZw\r
+       5jJKnJ78igmkn01AQ2Lb/uVgs0QEpCV23p3NCmIzC0RLHLk8gw3EFhawlDjVs5EFxGYRUJXo\r
+       3/+dGcTmFXCUOPXzFDPEHUoSC09tA+vlBIr/fH0NbKaQgIPEr99nWCYw8i9gZFjFKJuSW6Wb\r
+       m5iZU5yarFucnJiXl1qka6qXm1mil5pSuokRFFzsLko7GH8eVDrEKMDBqMTDq/EhPUiINbGs\r
+       uDL3EKMkB5OSKO8908wgIb6k/JTKjMTijPii0pzU4kOMEhzMSiK80/SAcrwpiZVVqUX5MClp\r
+       DhYlcd5bHPZBQgLpiSWp2ampBalFMFkZDg4lCV5/S6BGwaLU9NSKtMycEoQ0EwcnyHAeoOHp\r
+       IDW8xQWJucWZ6RD5U4yKUuK8SSAJAZBERmkeXC8s+l8xigO9IsxbDlLFA0wccN2vgAYzAQ2e\r
+       siQNZHBJIkJKqoFRrfKAl6dM0HkmtqSpfd07TU4VVvy1iNghu1sijWnprqz628/eqycs3H3p\r
+       jkacf7btT+6kv5aGd2ovWhittdpzX1mHuThs8414dd/rM5Y8uXZNbPe31aH+8199Xsy0SXqJ\r
+       9k2eKIFtn0Kt36flPfaXUQmVkZ42Qa/+YaflN/YM6w2FMx3Wzb2uxFKckWioxVxUnAgA8FCt\r
+       ktkCAAA=\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+       <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://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: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Thu, 24 Oct 2013 15:19:50 -0000\r
+\r
+This fixes races in thread-local and global tagging in notmuch-search\r
+(e.g., "+", "-", "a", "*", etc.).  Previously, these would modify tags\r
+of new messages that arrived after the search.  Now they only operate\r
+on the messages that were in the threads when the search was\r
+performed.  This prevents surprises like archiving messages that\r
+arrived in a thread after the search results were shown.\r
+\r
+This eliminates `notmuch-search-find-thread-id-region(-search)'\r
+because these functions strongly encouraged racy usage.\r
+\r
+This fixes the two broken tests added by the previous patch.\r
+---\r
+ devel/TODO       |  5 -----\r
+ emacs/notmuch.el | 40 +++++++++++++++++++++++++++-------------\r
+ test/emacs       |  4 +---\r
+ 3 files changed, 28 insertions(+), 21 deletions(-)\r
+\r
+diff --git a/devel/TODO b/devel/TODO\r
+index f212483..1cf4089 100644\r
+--- a/devel/TODO\r
++++ b/devel/TODO\r
+@@ -14,11 +14,6 @@ sender's name containing ';' which causes emacs to drop a search\r
+ result.) This may require removing the outer array from the current\r
+ "notmuch search --format=json" results.\r
\r
+-Fix '*' to work by simply calling '+' or '-' on a region consisting of\r
+-the entire buffer, (this would avoid one race condition---while still\r
+-leaving other race conditions---but could also potentially make '*' a\r
+-very expensive operation).\r
+-\r
+ Add a global keybinding table for notmuch, and then view-specific\r
+ tables that add to it.\r
+       \r
+diff --git a/emacs/notmuch.el b/emacs/notmuch.el\r
+index 496c8ec..fea1a93 100644\r
+--- a/emacs/notmuch.el\r
++++ b/emacs/notmuch.el\r
+@@ -485,14 +485,25 @@ If BARE is set then do not prefix with \"thread:\""\r
+   (let ((thread (plist-get (notmuch-search-get-result) :thread)))\r
+     (when thread (concat (unless bare "thread:") thread))))\r
\r
+-(defun notmuch-search-find-thread-id-region (beg end)\r
+-  "Return a list of threads for the current region"\r
+-  (mapcar (lambda (thread) (concat "thread:" thread))\r
+-        (notmuch-search-properties-in-region :thread beg end)))\r
+-\r
+-(defun notmuch-search-find-thread-id-region-search (beg end)\r
+-  "Return a search string for threads for the current region"\r
+-  (mapconcat 'identity (notmuch-search-find-thread-id-region beg end) " or "))\r
++(defun notmuch-search-find-stable-query ()\r
++  "Return the stable queries for the current thread.\r
++\r
++This returns a list (MATCHED-QUERY UNMATCHED-QUERY) for the\r
++matched and unmatched messages in the current thread."\r
++  (plist-get (notmuch-search-get-result) :query))\r
++\r
++(defun notmuch-search-find-stable-query-region (beg end &optional only-matched)\r
++  "Return the stable query for the current region.\r
++\r
++If ONLY-MATCHED is non-nil, include only matched messages.  If it\r
++is nil, include both matched and unmatched messages."\r
++  (let ((query-list nil) (all (not only-matched)))\r
++    (dolist (queries (notmuch-search-properties-in-region :query beg end))\r
++      (when (first queries)\r
++      (push (first queries) query-list))\r
++      (when (and all (second queries))\r
++      (push (second queries) query-list)))\r
++    (concat "(" (mapconcat 'identity query-list ") or (") ")")))\r
\r
+ (defun notmuch-search-find-authors ()\r
+   "Return the authors for the current thread"\r
+@@ -569,17 +580,20 @@ Returns (TAG-CHANGES REGION-BEGIN REGION-END)."\r
+          (notmuch-search-get-tags-region beg end) prompt initial-input)\r
+         region)))\r
\r
+-(defun notmuch-search-tag (tag-changes &optional beg end)\r
++(defun notmuch-search-tag (tag-changes &optional beg end only-matched)\r
+   "Change tags for the currently selected thread or region.\r
\r
+ See `notmuch-tag' for information on the format of TAG-CHANGES.\r
+ When called interactively, this uses the region if the region is\r
+ active.  When called directly, BEG and END provide the region.\r
+ If these are nil or not provided, this applies to the thread at\r
+-point."\r
++point.\r
++\r
++If ONLY-MATCHED is non-nil, only tag matched messages."\r
+   (interactive (notmuch-search-interactive-tag-changes))\r
+   (unless (and beg end) (setq beg (point) end (point)))\r
+-  (let ((search-string (notmuch-search-find-thread-id-region-search beg end)))\r
++  (let ((search-string (notmuch-search-find-stable-query-region\r
++                      beg end only-matched)))\r
+     (notmuch-tag search-string tag-changes)\r
+     (notmuch-search-foreach-result beg end\r
+       (lambda (pos)\r
+@@ -847,7 +861,7 @@ See `notmuch-tag' for information on the format of TAG-CHANGES."\r
+   (interactive\r
+    (list (notmuch-read-tag-changes\r
+         (notmuch-search-get-tags-region (point-min) (point-max)) "Tag all")))\r
+-  (notmuch-tag notmuch-search-query-string tag-changes))\r
++  (notmuch-search-tag tag-changes (point-min) (point-max) t))\r
\r
+ (defun notmuch-search-buffer-title (query)\r
+   "Returns the title for a buffer with notmuch search results."\r
+@@ -951,7 +965,7 @@ the configured default sort order."\r
+       (save-excursion\r
+       (let ((proc (notmuch-start-notmuch\r
+                    "notmuch-search" buffer #'notmuch-search-process-sentinel\r
+-                   "search" "--format=sexp" "--format-version=1"\r
++                   "search" "--format=sexp" "--format-version=2"\r
+                    (if oldest-first\r
+                        "--sort=oldest-first"\r
+                      "--sort=newest-first")\r
+diff --git a/test/emacs b/test/emacs\r
+index 7503e96..3b3b14d 100755\r
+--- a/test/emacs\r
++++ b/test/emacs\r
+@@ -889,7 +889,7 @@ $PWD/notmuch_fail exited with status 1 (see *Notmuch errors* for more details)\r
+ ---\r
+ [XXX]\r
+ $PWD/notmuch_fail exited with status 1\r
+-command: $PWD/notmuch_fail search --format\=sexp --format-version\=1 --sort\=newest-first tag\:inbox\r
++command: $PWD/notmuch_fail search --format\=sexp --format-version\=2 --sort\=newest-first tag\:inbox\r
+ exit status: 1"\r
\r
+ test_begin_subtest "Search handles subprocess warnings"\r
+@@ -923,7 +923,6 @@ This is a warning\r
+ This is another warning"\r
\r
+ test_begin_subtest "Search thread tag operations are race-free"\r
+-test_subtest_known_broken\r
+ add_message '[subject]="Search race test"'\r
+ gen_msg_id_1=$gen_msg_id\r
+ generate_message '[in-reply-to]="<'$gen_msg_id_1'>"' \\r
+@@ -937,7 +936,6 @@ output=$(notmuch search --output=messages 'tag:search-thread-race-tag')\r
+ test_expect_equal "$output" "id:$gen_msg_id_1"\r
\r
+ test_begin_subtest "Search global tag operations are race-free"\r
+-test_subtest_known_broken\r
+ generate_message '[in-reply-to]="<'$gen_msg_id_1'>"' \\r
+           '[references]="<'$gen_msg_id_1'>"' \\r
+           '[subject]="Re: Search race test"'\r
+-- \r
+1.8.4.rc3\r
+\r