X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=notmuch-new.c;h=9d206167e997382d623934ce4dd1797751b2e950;hp=127c9db11e11dc74b0c37a7d489522982f3fcdee;hb=4faf809578ca63edc9f23f92d7ce47d60dbc061e;hpb=22759fb27995a8bb1c702e68fd12aee5f40da143 diff --git a/notmuch-new.c b/notmuch-new.c index 127c9db1..9d206167 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -20,6 +20,8 @@ #include "notmuch-client.h" +#include + static volatile sig_atomic_t do_add_files_print_progress = 0; static void @@ -33,8 +35,10 @@ static volatile sig_atomic_t interrupted; static void handle_sigint (unused (int sig)) { + ssize_t ignored; static char msg[] = "Stopping... \n"; - write(2, msg, sizeof(msg)-1); + + ignored = write(2, msg, sizeof(msg)-1); interrupted = 1; } @@ -78,6 +82,33 @@ static int ino_cmp(const struct dirent **a, const struct dirent **b) return ((*a)->d_ino < (*b)->d_ino) ? -1 : 1; } +/* Test if the directory looks like a Maildir directory. + * + * Search through the array of directory entries to see if we can find all + * three subdirectories typical for Maildir, that is "new", "cur", and "tmp". + * + * Return 1 if the directory looks like a Maildir and 0 otherwise. + */ +static int +is_maildir (struct dirent **entries, int count) +{ + int i, found = 0; + + for (i = 0; i < count; i++) { + if (entries[i]->d_type != DT_DIR) continue; + if (strcmp(entries[i]->d_name, "new") == 0 || + strcmp(entries[i]->d_name, "cur") == 0 || + strcmp(entries[i]->d_name, "tmp") == 0) + { + found++; + if (found == 3) + return 1; + } + } + + return 0; +} + /* Examine 'path' recursively as follows: * * o Ask the filesystem for the mtime of 'path' (path_mtime) @@ -147,7 +178,7 @@ add_files_recursive (notmuch_database_t *notmuch, /* If this directory hasn't been modified since the last * add_files, then we only need to look further for * sub-directories. */ - if (path_mtime <= path_dbtime && entry->d_type != DT_DIR) + if (path_mtime <= path_dbtime && entry->d_type == DT_REG) continue; /* Ignore special directories to avoid infinite recursion. @@ -157,6 +188,9 @@ add_files_recursive (notmuch_database_t *notmuch, * user specify files to be ignored. */ if (strcmp (entry->d_name, ".") == 0 || strcmp (entry->d_name, "..") == 0 || + (entry->d_type == DT_DIR && + (strcmp (entry->d_name, "tmp") == 0) && + is_maildir (namelist, num_entries)) || strcmp (entry->d_name, ".notmuch") ==0) { continue; @@ -165,10 +199,21 @@ add_files_recursive (notmuch_database_t *notmuch, next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name); if (stat (next, st)) { + int err = errno; + + switch (err) { + case ENOENT: + /* The file was removed between scandir and now... */ + case EPERM: + case EACCES: + /* We can't read this file so don't add it to the cache. */ + continue; + } + fprintf (stderr, "Error reading %s: %s\n", next, strerror (errno)); ret = NOTMUCH_STATUS_FILE_ERROR; - continue; + goto DONE; } if (S_ISREG (st->st_mode)) { @@ -177,6 +222,19 @@ add_files_recursive (notmuch_database_t *notmuch, if (path_dbtime == 0 || st->st_mtime > path_dbtime) { state->processed_files++; + if (state->verbose) { + if (state->output_is_a_tty) + printf("\r\033[K"); + + printf ("%i/%i: %s", + state->processed_files, + state->total_files, + next); + + putchar((state->output_is_a_tty) ? '\r' : '\n'); + fflush (stdout); + } + status = notmuch_database_add_message (notmuch, next, &message); switch (status) { /* success */ @@ -193,6 +251,7 @@ add_files_recursive (notmuch_database_t *notmuch, next); break; /* Fatal issues. Don't process anymore. */ + case NOTMUCH_STATUS_READONLY_DATABASE: case NOTMUCH_STATUS_XAPIAN_EXCEPTION: case NOTMUCH_STATUS_OUT_OF_MEMORY: fprintf (stderr, "Error: %s. Halting processing.\n", @@ -258,6 +317,7 @@ add_files (notmuch_database_t *notmuch, notmuch_status_t status; struct sigaction action; struct itimerval timerval; + notmuch_bool_t timer_is_active = FALSE; if (stat (path, &st)) { fprintf (stderr, "Error reading directory %s: %s\n", @@ -270,32 +330,38 @@ add_files (notmuch_database_t *notmuch, return NOTMUCH_STATUS_FILE_ERROR; } - /* Setup our handler for SIGALRM */ - memset (&action, 0, sizeof (struct sigaction)); - action.sa_handler = handle_sigalrm; - sigemptyset (&action.sa_mask); - action.sa_flags = SA_RESTART; - sigaction (SIGALRM, &action, NULL); - - /* Then start a timer to send SIGALRM once per second. */ - timerval.it_interval.tv_sec = 1; - timerval.it_interval.tv_usec = 0; - timerval.it_value.tv_sec = 1; - timerval.it_value.tv_usec = 0; - setitimer (ITIMER_REAL, &timerval, NULL); + if (state->output_is_a_tty && ! debugger_is_active () && ! state->verbose) { + /* Setup our handler for SIGALRM */ + memset (&action, 0, sizeof (struct sigaction)); + action.sa_handler = handle_sigalrm; + sigemptyset (&action.sa_mask); + action.sa_flags = SA_RESTART; + sigaction (SIGALRM, &action, NULL); + + /* Then start a timer to send SIGALRM once per second. */ + timerval.it_interval.tv_sec = 1; + timerval.it_interval.tv_usec = 0; + timerval.it_value.tv_sec = 1; + timerval.it_value.tv_usec = 0; + setitimer (ITIMER_REAL, &timerval, NULL); + + timer_is_active = TRUE; + } status = add_files_recursive (notmuch, path, &st, state); - /* Now stop the timer. */ - timerval.it_interval.tv_sec = 0; - timerval.it_interval.tv_usec = 0; - timerval.it_value.tv_sec = 0; - timerval.it_value.tv_usec = 0; - setitimer (ITIMER_REAL, &timerval, NULL); - - /* And disable the signal handler. */ - action.sa_handler = SIG_IGN; - sigaction (SIGALRM, &action, NULL); + if (timer_is_active) { + /* Now stop the timer. */ + timerval.it_interval.tv_sec = 0; + timerval.it_interval.tv_usec = 0; + timerval.it_value.tv_sec = 0; + timerval.it_value.tv_usec = 0; + setitimer (ITIMER_REAL, &timerval, NULL); + + /* And disable the signal handler. */ + action.sa_handler = SIG_IGN; + sigaction (SIGALRM, &action, NULL); + } return status; } @@ -309,37 +375,25 @@ add_files (notmuch_database_t *notmuch, static void count_files (const char *path, int *count) { - DIR *dir; - struct dirent *e, *entry = NULL; - int entry_length; - int err; + struct dirent *entry = NULL; char *next; struct stat st; + struct dirent **namelist = NULL; + int n_entries = scandir (path, &namelist, 0, ino_cmp); + int i = 0; - dir = opendir (path); - - if (dir == NULL) { + if (n_entries == -1) { fprintf (stderr, "Warning: failed to open directory %s: %s\n", path, strerror (errno)); goto DONE; } - entry_length = offsetof (struct dirent, d_name) + - pathconf (path, _PC_NAME_MAX) + 1; - entry = malloc (entry_length); - while (!interrupted) { - err = readdir_r (dir, entry, &e); - if (err) { - fprintf (stderr, "Error reading directory: %s\n", - strerror (errno)); - free (entry); - goto DONE; - } - - if (e == NULL) + if (i == n_entries) break; + entry= namelist[i++]; + /* Ignore special directories to avoid infinite recursion. * Also ignore the .notmuch directory. */ @@ -377,13 +431,12 @@ count_files (const char *path, int *count) DONE: if (entry) free (entry); - - closedir (dir); + if (namelist) + free (namelist); } int -notmuch_new_command (void *ctx, - unused (int argc), unused (char *argv[])) +notmuch_new_command (void *ctx, int argc, char *argv[]) { notmuch_config_t *config; notmuch_database_t *notmuch; @@ -395,6 +448,19 @@ notmuch_new_command (void *ctx, const char *db_path; char *dot_notmuch_path; struct sigaction action; + int i; + + add_files_state.verbose = 0; + add_files_state.output_is_a_tty = isatty (fileno (stdout)); + + for (i = 0; i < argc && argv[i][0] == '-'; i++) { + if (STRNCMP_LITERAL (argv[i], "--verbose") == 0) { + add_files_state.verbose = 1; + } else { + fprintf (stderr, "Unrecognized option: %s\n", argv[i]); + return 1; + } + } /* Setup our handler for SIGINT */ memset (&action, 0, sizeof (struct sigaction)); @@ -419,11 +485,13 @@ notmuch_new_command (void *ctx, if (interrupted) return 1; + printf ("Found %d total files. \n", count); notmuch = notmuch_database_create (db_path); add_files_state.ignore_read_only_directories = FALSE; add_files_state.total_files = count; } else { - notmuch = notmuch_database_open (db_path); + notmuch = notmuch_database_open (db_path, + NOTMUCH_DATABASE_MODE_READ_WRITE); add_files_state.ignore_read_only_directories = TRUE; add_files_state.total_files = 0; } @@ -435,7 +503,6 @@ notmuch_new_command (void *ctx, dot_notmuch_path = NULL; add_files_state.saw_read_only_directory = FALSE; - add_files_state.total_files = 0; add_files_state.processed_files = 0; add_files_state.added_messages = 0; gettimeofday (&add_files_state.tv_start, NULL);