--- /dev/null
+Return-Path: <dottedmag@dottedmag.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 olra.theworths.org (Postfix) with ESMTP id 1FEFE431FBC\r
+ for <notmuch@notmuchmail.org>; Thu, 26 Nov 2009 12:23:51 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\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 yqSzF81pNVVO for <notmuch@notmuchmail.org>;\r
+ Thu, 26 Nov 2009 12:23:50 -0800 (PST)\r
+Received: from dottedmag.net (burger.dottedmag.net [212.75.37.82])\r
+ by olra.theworths.org (Postfix) with ESMTP id 922B7431FAE\r
+ for <notmuch@notmuchmail.org>; Thu, 26 Nov 2009 12:23:49 -0800 (PST)\r
+Received: from vertex.dottedmag (unknown [91.197.127.125])\r
+ by dottedmag.net (Postfix) with ESMTPSA id 2C6788C025\r
+ for <notmuch@notmuchmail.org>; Thu, 26 Nov 2009 21:23:48 +0100 (CET)\r
+Received: from dottedmag by vertex.dottedmag with local (Exim 4.69)\r
+ (envelope-from <dottedmag@dottedmag.net>) id 1NDksT-0007U0-55\r
+ for notmuch@notmuchmail.org; Fri, 27 Nov 2009 02:23:45 +0600\r
+From: Mikhail Gusarov <dottedmag@dottedmag.net>\r
+To: notmuch@notmuchmail.org\r
+Date: Fri, 27 Nov 2009 02:23:45 +0600\r
+Message-Id: <1259267025-28733-1-git-send-email-dottedmag@dottedmag.net>\r
+X-Mailer: git-send-email 1.6.3.3\r
+Subject: [notmuch] [PATCH] Handle message renames in mail spool\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.12\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, 26 Nov 2009 20:23:51 -0000\r
+\r
+In order to handle message renames the following changes were deemed necessary:\r
+\r
+* Mtime check on individual files was disabled. As files may be moved around\r
+without changing their mtime, it's necessary to parse them even if they appear\r
+old in case old message was moved. mtime check on directories was kept as moving\r
+files changes mtime of directory.\r
+\r
+* If message being parsed is already found in database under different path,\r
+then this message is considered to be moved, path is updated in database and\r
+this file does not undergo further processing.\r
+\r
+Note that after applying this patch notmuch still does not handle copying files\r
+(which is harmless, database will point to the last copy of message found during\r
+'notmuch new') and deleting files (which is more serious, as dangling entries\r
+will show up in searches).\r
+\r
+Signed-off-by: Mikhail Gusarov <dottedmag@dottedmag.net>\r
+---\r
+ lib/database.cc | 32 +++++++++++++------\r
+ notmuch-new.c | 92 ++++++++++++++++++++++++++----------------------------\r
+ 2 files changed, 66 insertions(+), 58 deletions(-)\r
+\r
+diff --git a/lib/database.cc b/lib/database.cc\r
+index 2c90019..257c0b8 100644\r
+--- a/lib/database.cc\r
++++ b/lib/database.cc\r
+@@ -990,19 +990,31 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
+ if (private_status == NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) {\r
+ _notmuch_message_set_filename (message, filename);\r
+ _notmuch_message_add_term (message, "type", "mail");\r
+- } else {\r
+- ret = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;\r
+- goto DONE;\r
+- }\r
+ \r
+- ret = _notmuch_database_link_message (notmuch, message, message_file);\r
+- if (ret)\r
+- goto DONE;\r
++ ret = _notmuch_database_link_message (notmuch, message, message_file);\r
++ if (ret)\r
++ goto DONE;\r
+ \r
+- date = notmuch_message_file_get_header (message_file, "date");\r
+- _notmuch_message_set_date (message, date);\r
++ date = notmuch_message_file_get_header (message_file, "date");\r
++ _notmuch_message_set_date (message, date);\r
+ \r
+- _notmuch_message_index_file (message, filename);\r
++ _notmuch_message_index_file (message, filename);\r
++ } else {\r
++ const char *old_filename = notmuch_message_get_filename (message);\r
++ if (strcmp (old_filename, filename) == 0) {\r
++ /* We have already seen it */\r
++ goto DONE;\r
++ } else {\r
++ if (access (old_filename, R_OK) == 0) {\r
++ /* old_filename still exists, we've got a duplicate */\r
++ ret = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;\r
++ goto DONE;\r
++ } else {\r
++ /* Message file has been moved/renamed */\r
++ _notmuch_message_set_filename (message, filename);\r
++ }\r
++ }\r
++ }\r
+ \r
+ _notmuch_message_sync (message);\r
+ } catch (const Xapian::Error &error) {\r
+diff --git a/notmuch-new.c b/notmuch-new.c\r
+index 0dd2784..d16679c 100644\r
+--- a/notmuch-new.c\r
++++ b/notmuch-new.c\r
+@@ -174,54 +174,50 @@ add_files_recursive (notmuch_database_t *notmuch,\r
+ }\r
+ \r
+ if (S_ISREG (st->st_mode)) {\r
+- /* If the file hasn't been modified since the last\r
+- * add_files, then we need not look at it. */\r
+- if (path_dbtime == 0 || st->st_mtime > path_dbtime) {\r
+- state->processed_files++;\r
+-\r
+- status = notmuch_database_add_message (notmuch, next, &message);\r
+- switch (status) {\r
+- /* success */\r
+- case NOTMUCH_STATUS_SUCCESS:\r
+- state->added_messages++;\r
+- tag_inbox_and_unread (message);\r
+- break;\r
+- /* Non-fatal issues (go on to next file) */\r
+- case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:\r
+- /* Stay silent on this one. */\r
+- break;\r
+- case NOTMUCH_STATUS_FILE_NOT_EMAIL:\r
+- fprintf (stderr, "Note: Ignoring non-mail file: %s\n",\r
+- next);\r
+- break;\r
+- /* Fatal issues. Don't process anymore. */\r
+- case NOTMUCH_STATUS_READONLY_DATABASE:\r
+- case NOTMUCH_STATUS_XAPIAN_EXCEPTION:\r
+- case NOTMUCH_STATUS_OUT_OF_MEMORY:\r
+- fprintf (stderr, "Error: %s. Halting processing.\n",\r
+- notmuch_status_to_string (status));\r
+- ret = status;\r
+- goto DONE;\r
+- default:\r
+- case NOTMUCH_STATUS_FILE_ERROR:\r
+- case NOTMUCH_STATUS_NULL_POINTER:\r
+- case NOTMUCH_STATUS_TAG_TOO_LONG:\r
+- case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:\r
+- case NOTMUCH_STATUS_LAST_STATUS:\r
+- INTERNAL_ERROR ("add_message returned unexpected value: %d", status);\r
+- goto DONE;\r
+- }\r
+-\r
+- if (message) {\r
+- notmuch_message_destroy (message);\r
+- message = NULL;\r
+- }\r
+-\r
+- if (do_add_files_print_progress) {\r
+- do_add_files_print_progress = 0;\r
+- add_files_print_progress (state);\r
+- }\r
+- }\r
++ state->processed_files++;\r
++\r
++ status = notmuch_database_add_message (notmuch, next, &message);\r
++ switch (status) {\r
++ /* success */\r
++ case NOTMUCH_STATUS_SUCCESS:\r
++ state->added_messages++;\r
++ tag_inbox_and_unread (message);\r
++ break;\r
++ /* Non-fatal issues (go on to next file) */\r
++ case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:\r
++ /* Stay silent on this one. */\r
++ break;\r
++ case NOTMUCH_STATUS_FILE_NOT_EMAIL:\r
++ fprintf (stderr, "Note: Ignoring non-mail file: %s\n",\r
++ next);\r
++ break;\r
++ /* Fatal issues. Don't process anymore. */\r
++ case NOTMUCH_STATUS_READONLY_DATABASE:\r
++ case NOTMUCH_STATUS_XAPIAN_EXCEPTION:\r
++ case NOTMUCH_STATUS_OUT_OF_MEMORY:\r
++ fprintf (stderr, "Error: %s. Halting processing.\n",\r
++ notmuch_status_to_string (status));\r
++ ret = status;\r
++ goto DONE;\r
++ default:\r
++ case NOTMUCH_STATUS_FILE_ERROR:\r
++ case NOTMUCH_STATUS_NULL_POINTER:\r
++ case NOTMUCH_STATUS_TAG_TOO_LONG:\r
++ case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:\r
++ case NOTMUCH_STATUS_LAST_STATUS:\r
++ INTERNAL_ERROR ("add_message returned unexpected value: %d", status);\r
++ goto DONE;\r
++ }\r
++\r
++ if (message) {\r
++ notmuch_message_destroy (message);\r
++ message = NULL;\r
++ }\r
++\r
++ if (do_add_files_print_progress) {\r
++ do_add_files_print_progress = 0;\r
++ add_files_print_progress (state);\r
++ }\r
+ } else if (S_ISDIR (st->st_mode)) {\r
+ status = add_files_recursive (notmuch, next, st, state);\r
+ if (status && ret == NOTMUCH_STATUS_SUCCESS)\r
+-- \r
+1.6.3.3\r
+\r