X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=notmuch-new.c;h=7d17793b2f382c5102f092a6e9173966286fa724;hp=1473d2e69449c80e596b0440bbd6269c31d8fd61;hb=bb2b33fbb85b88eb7d3bedf4cb261a89da20f504;hpb=90a505373ef5a8135357f2da3cdf6837e32c3a7a diff --git a/notmuch-new.c b/notmuch-new.c index 1473d2e6..7d17793b 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -64,10 +64,9 @@ static volatile sig_atomic_t interrupted; static void handle_sigint (unused (int sig)) { - ssize_t ignored; static char msg[] = "Stopping... \n"; - ignored = write(2, msg, sizeof(msg)-1); + write(2, msg, sizeof(msg)-1); interrupted = 1; } @@ -117,15 +116,19 @@ generic_print_progress (const char *action, const char *object, printf ("%s %d ", action, processed); if (total) { - double time_remaining; - - time_remaining = ((total - processed) / rate_overall); - printf ("of %d %s (", total, object); - notmuch_time_print_formatted_seconds (time_remaining); - printf (" remaining).\033[K\r"); + printf ("of %d %s", total, object); + if (processed > 0 && elapsed_overall > 0.5) { + double time_remaining = ((total - processed) / rate_overall); + printf (" ("); + notmuch_time_print_formatted_seconds (time_remaining); + printf (" remaining)"); + } } else { - printf ("%s (%d %s/sec.)\033[K\r", object, (int) rate_overall, object); + printf ("%s", object); + if (elapsed_overall > 0.5) + printf (" (%d %s/sec.)", (int) rate_overall, object); } + printf (".\033[K\r"); fflush (stdout); } @@ -178,15 +181,20 @@ _entries_resemble_maildir (struct dirent **entries, int count) * * o Ask the filesystem for files and directories within 'path' * (via scandir and stored in fs_entries) - * o Ask the database for files and directories within 'path' - * (db_files and db_subdirs) * * o Pass 1: For each directory in fs_entries, recursively call into * this same function. * - * o Pass 2: If 'fs_mtime' > 'db_mtime', then walk fs_entries - * simultaneously with db_files and db_subdirs. Look for one of - * three interesting cases: + * o Compare fs_mtime to db_mtime. If they are equivalent, terminate + * the algorithm at this point, (this directory has not been + * updated in the filesystem since the last database scan of PASS + * 2). + * + * o Ask the database for files and directories within 'path' + * (db_files and db_subdirs) + * + * o Pass 2: Walk fs_entries simultaneously with db_files and + * db_subdirs. Look for one of three interesting cases: * * 1. Regular file in fs_entries and not in db_files * This is a new file to add_message into the database. @@ -205,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, @@ -222,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; @@ -231,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 @@ -243,15 +254,26 @@ add_files_recursive (notmuch_database_t *notmuch, directory = notmuch_database_get_directory (notmuch, path); db_mtime = notmuch_directory_get_mtime (directory); - if (db_mtime == 0) { - new_directory = TRUE; - db_files = NULL; - db_subdirs = NULL; - } else { - new_directory = FALSE; - db_files = notmuch_directory_get_child_files (directory); - db_subdirs = notmuch_directory_get_child_directories (directory); - } + 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 @@ -324,6 +346,14 @@ add_files_recursive (notmuch_database_t *notmuch, if (fs_mtime == db_mtime) goto DONE; + /* new_directory means a directory that the database has never + * seen before. In that case, we can simply leave db_files and + * db_subdirs NULL. */ + if (!new_directory) { + db_files = notmuch_directory_get_child_files (directory); + db_subdirs = notmuch_directory_get_child_directories (directory); + } + /* Pass 2: Scan for new files, removed files, and removed directories. */ for (i = 0; i < num_fs_entries; i++) { @@ -365,7 +395,7 @@ add_files_recursive (notmuch_database_t *notmuch, /* If we're looking at a symlink, we only want to add it if it * links to a regular file, (and not to a directory, say). * - * Similarly, if the file is of unknown type (due to filesytem + * Similarly, if the file is of unknown type (due to filesystem * limitations), then we also need to look closer. * * In either case, a stat does the trick. @@ -501,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;