--- /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 A3700431FBC\r
+ for <notmuch@notmuchmail.org>; Wed, 2 Dec 2009 13:15:32 -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 FoTs+tuwF+-g for <notmuch@notmuchmail.org>;\r
+ Wed, 2 Dec 2009 13:15:31 -0800 (PST)\r
+Received: from dottedmag.net (burger.dottedmag.net [212.75.37.82])\r
+ by olra.theworths.org (Postfix) with ESMTP id 5B809431FAE\r
+ for <notmuch@notmuchmail.org>; Wed, 2 Dec 2009 13:15:31 -0800 (PST)\r
+Received: from vertex.dottedmag (unknown [91.197.127.125])\r
+ by dottedmag.net (Postfix) with ESMTPSA id 700028C9BF\r
+ for <notmuch@notmuchmail.org>; Wed, 2 Dec 2009 22:15:29 +0100 (CET)\r
+Received: from dottedmag by vertex.dottedmag with local (Exim 4.69)\r
+ (envelope-from <dottedmag@dottedmag.net>) id 1NFwXm-0003hd-Se\r
+ for notmuch@notmuchmail.org; Thu, 03 Dec 2009 03:15:26 +0600\r
+From: Mikhail Gusarov <dottedmag@dottedmag.net>\r
+To: notmuch@notmuchmail.org\r
+Date: Thu, 3 Dec 2009 03:15:26 +0600\r
+Message-Id: <1259788526-14205-1-git-send-email-dottedmag@dottedmag.net>\r
+X-Mailer: git-send-email 1.6.3.3\r
+In-Reply-To: <1259267025-28733-1-git-send-email-dottedmag@dottedmag.net>\r
+References: <1259267025-28733-1-git-send-email-dottedmag@dottedmag.net>\r
+Subject: [notmuch] [PATCH (rebased)] 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: Wed, 02 Dec 2009 21:15:32 -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 | 116 ++++++++++++++++++++++++++----------------------------\r
+ 2 files changed, 78 insertions(+), 70 deletions(-)\r
+\r
+diff --git a/lib/database.cc b/lib/database.cc\r
+index 23ddd4a..45d8fc7 100644\r
+--- a/lib/database.cc\r
++++ b/lib/database.cc\r
+@@ -993,19 +993,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 9d20616..d595fc4 100644\r
+--- a/notmuch-new.c\r
++++ b/notmuch-new.c\r
+@@ -217,66 +217,62 @@ 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
+- if (state->verbose) {\r
+- if (state->output_is_a_tty)\r
+- printf("\r\033[K");\r
+-\r
+- printf ("%i/%i: %s",\r
+- state->processed_files,\r
+- state->total_files,\r
+- next);\r
+-\r
+- putchar((state->output_is_a_tty) ? '\r' : '\n');\r
+- fflush (stdout);\r
+- }\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
++ state->processed_files++;\r
++\r
++ if (state->verbose) {\r
++ if (state->output_is_a_tty)\r
++ printf("\r\033[K");\r
++\r
++ printf ("%i/%i: %s",\r
++ state->processed_files,\r
++ state->total_files,\r
++ next);\r
++\r
++ putchar((state->output_is_a_tty) ? '\r' : '\n');\r
++ fflush (stdout);\r
++ }\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
+-- \r
+1.6.3.3\r
+\r