]> git.notmuchmail.org Git - notmuch/blobdiff - notmuch-new.c
new: Improved workaround for mistaken new directories
[notmuch] / notmuch-new.c
index 0fa2a3cb72ebcda4a3de4131d3106a0fa4a96704..7d17793b2f382c5102f092a6e9173966286fa724 100644 (file)
@@ -213,6 +213,7 @@ _entries_resemble_maildir (struct dirent **entries, int count)
  *     information is lost from the database).
  *
  *   o Tell the database to update its time of 'path' to 'fs_mtime'
+ *     if fs_mtime isn't the current wall-clock time.
  */
 static notmuch_status_t
 add_files_recursive (notmuch_database_t *notmuch,
@@ -230,6 +231,7 @@ add_files_recursive (notmuch_database_t *notmuch,
     notmuch_directory_t *directory;
     notmuch_filenames_t *db_files = NULL;
     notmuch_filenames_t *db_subdirs = NULL;
+    time_t stat_time;
     struct stat st;
     notmuch_bool_t is_maildir, new_directory;
     const char **tag;
@@ -239,6 +241,7 @@ add_files_recursive (notmuch_database_t *notmuch,
                 path, strerror (errno));
        return NOTMUCH_STATUS_FILE_ERROR;
     }
+    stat_time = time (NULL);
 
     /* This is not an error since we may have recursed based on a
      * symlink to a regular file, not a directory, and we don't know
@@ -253,6 +256,25 @@ add_files_recursive (notmuch_database_t *notmuch,
 
     new_directory = db_mtime ? FALSE : TRUE;
 
+    /* XXX This is a temporary workaround.  If we don't update the
+     * database mtime until after processing messages in this
+     * directory, then a 0 mtime is *not* sufficient to indicate that
+     * this directory has no messages or subdirs in the database (for
+     * example, if an earlier run skipped the mtime update because
+     * fs_mtime == stat_time, or was interrupted before updating the
+     * mtime at the end).  To address this, we record a (bogus)
+     * non-zero value before processing any child messages so that a
+     * later run won't mistake this for a new directory (and, for
+     * example, fail to detect removed files and subdirs).
+     *
+     * A better solution would be for notmuch_database_get_directory
+     * to indicate if it really created a new directory or not, either
+     * by a new out-argument, or by recording this information and
+     * providing an accessor.
+     */
+    if (new_directory)
+       notmuch_directory_set_mtime (directory, -1);
+
     /* If the database knows about this directory, then we sort based
      * on strcmp to match the database sorting. Otherwise, we can do
      * inode-based sorting for faster filesystem operation. */
@@ -509,7 +531,12 @@ add_files_recursive (notmuch_database_t *notmuch,
        notmuch_filenames_move_to_next (db_subdirs);
     }
 
-    if (! interrupted) {
+    /* If the directory's mtime is the same as the wall-clock time
+     * when we stat'ed the directory, we skip updating the mtime in
+     * the database because a message could be delivered later in this
+     * same second.  This may lead to unnecessary re-scans, but it
+     * avoids overlooking messages. */
+    if (! interrupted && fs_mtime != stat_time) {
        status = notmuch_directory_set_mtime (directory, fs_mtime);
        if (status && ret == NOTMUCH_STATUS_SUCCESS)
            ret = status;