]> git.notmuchmail.org Git - notmuch/blobdiff - notmuch-new.c
cli/new: Avoid printing "\033[K" to non-terminal output
[notmuch] / notmuch-new.c
index ddf42c140802225078dce5a7316609404a439930..e2822e23060786ee9674e3d9371cec44782315ba 100644 (file)
@@ -13,7 +13,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see http://www.gnu.org/licenses/ .
+ * along with this program.  If not, see https://www.gnu.org/licenses/ .
  *
  * Author: Carl Worth <cworth@cworth.org>
  */
@@ -53,6 +53,7 @@ typedef struct {
     int total_files;
     int processed_files;
     int added_messages, removed_messages, renamed_messages;
+    int vanished_files;
     struct timeval tv_start;
 
     _filename_list_t *removed_files;
@@ -280,6 +281,12 @@ add_file (notmuch_database_t *notmuch, const char *filename,
     case NOTMUCH_STATUS_FILE_NOT_EMAIL:
        fprintf (stderr, "Note: Ignoring non-mail file: %s\n", filename);
        break;
+    case NOTMUCH_STATUS_FILE_ERROR:
+       /* Someone renamed/removed the file between scandir and now. */
+       state->vanished_files++;
+       fprintf (stderr, "Unexpected error with file %s\n", filename);
+       (void) print_status_database ("add_file", notmuch, status);
+       break;
     /* Fatal issues. Don't process anymore. */
     case NOTMUCH_STATUS_READ_ONLY_DATABASE:
     case NOTMUCH_STATUS_XAPIAN_EXCEPTION:
@@ -347,7 +354,6 @@ add_files (notmuch_database_t *notmuch,
           const char *path,
           add_files_state_t *state)
 {
-    DIR *dir = NULL;
     struct dirent *entry = NULL;
     char *next = NULL;
     time_t fs_mtime, db_mtime;
@@ -445,7 +451,7 @@ add_files (notmuch_database_t *notmuch,
         */
        if (_entry_in_ignore_list (entry->d_name, state)) {
            if (state->debug)
-               printf ("(D) add_files_recursive, pass 1: explicitly ignoring %s/%s\n",
+               printf ("(D) add_files, pass 1: explicitly ignoring %s/%s\n",
                        path, entry->d_name);
            continue;
        }
@@ -513,9 +519,8 @@ add_files (notmuch_database_t *notmuch,
        /* Ignore files & directories user has configured to be ignored */
        if (_entry_in_ignore_list (entry->d_name, state)) {
            if (state->debug)
-               printf ("(D) add_files_recursive, pass 2: explicitly ignoring %s/%s\n",
-                       path,
-                       entry->d_name);
+               printf ("(D) add_files, pass 2: explicitly ignoring %s/%s\n",
+                       path, entry->d_name);
            continue;
        }
 
@@ -528,6 +533,10 @@ add_files (notmuch_database_t *notmuch,
                                              "%s/%s", path,
                                              notmuch_filenames_get (db_files));
 
+           if (state->debug)
+               printf ("(D) add_files, pass 2: queuing passed file %s for deletion from database\n",
+                       absolute);
+
            _filename_list_add (state->removed_files, absolute);
 
            notmuch_filenames_move_to_next (db_files);
@@ -542,6 +551,9 @@ add_files (notmuch_database_t *notmuch,
            {
                char *absolute = talloc_asprintf (state->removed_directories,
                                                  "%s/%s", path, filename);
+               if (state->debug)
+                   printf ("(D) add_files, pass 2: queuing passed directory %s for deletion from database\n",
+                       absolute);
 
                _filename_list_add (state->removed_directories, absolute);
            }
@@ -610,6 +622,9 @@ add_files (notmuch_database_t *notmuch,
        char *absolute = talloc_asprintf (state->removed_files,
                                          "%s/%s", path,
                                          notmuch_filenames_get (db_files));
+       if (state->debug)
+           printf ("(D) add_files, pass 3: queuing leftover file %s for deletion from database\n",
+                   absolute);
 
        _filename_list_add (state->removed_files, absolute);
 
@@ -622,6 +637,10 @@ add_files (notmuch_database_t *notmuch,
                                          "%s/%s", path,
                                          notmuch_filenames_get (db_subdirs));
 
+       if (state->debug)
+           printf ("(D) add_files, pass 3: queuing leftover directory %s for deletion from database\n",
+                   absolute);
+
        _filename_list_add (state->removed_directories, absolute);
 
        notmuch_filenames_move_to_next (db_subdirs);
@@ -638,8 +657,6 @@ add_files (notmuch_database_t *notmuch,
   DONE:
     if (next)
        talloc_free (next);
-    if (dir)
-       closedir (dir);
     if (fs_entries) {
        for (i = 0; i < num_fs_entries; i++)
            free (fs_entries[i]);
@@ -662,7 +679,7 @@ setup_progress_printing_timer (void)
     struct sigaction action;
     struct itimerval timerval;
 
-    /* Setup our handler for SIGALRM */
+    /* Set up our handler for SIGALRM */
     memset (&action, 0, sizeof (struct sigaction));
     action.sa_handler = handle_sigalrm;
     sigemptyset (&action.sa_mask);
@@ -721,18 +738,20 @@ count_files (const char *path, int *count, add_files_state_t *state)
         entry = fs_entries[i];
 
        /* Ignore special directories to avoid infinite recursion.
-        * Also ignore the .notmuch directory and files/directories
-        * the user has configured to be ignored.
+        * Also ignore the .notmuch directory.
         */
        if (strcmp (entry->d_name, ".") == 0 ||
            strcmp (entry->d_name, "..") == 0 ||
-           strcmp (entry->d_name, ".notmuch") == 0 ||
-           _entry_in_ignore_list (entry->d_name, state))
-       {
-           if (state->debug && _entry_in_ignore_list (entry->d_name, state))
+           strcmp (entry->d_name, ".notmuch") == 0)
+           continue;
+
+       /* Ignore any files/directories the user has configured to be
+        * ignored
+        */
+       if (_entry_in_ignore_list (entry->d_name, state)) {
+           if (state->debug)
                printf ("(D) count_files: explicitly ignoring %s/%s\n",
-                       path,
-                       entry->d_name);
+                       path, entry->d_name);
            continue;
        }
 
@@ -864,8 +883,11 @@ _remove_directory (void *ctx,
            goto DONE;
     }
 
+    status = notmuch_directory_delete (directory);
+
   DONE:
-    notmuch_directory_destroy (directory);
+    if (status)
+       notmuch_directory_destroy (directory);
     return status;
 }
 
@@ -883,10 +905,9 @@ print_results (const add_files_state_t *state)
                state->processed_files == 1 ? "file" : "total files");
        notmuch_time_print_formatted_seconds (elapsed);
        if (elapsed > 1)
-           printf (" (%d files/sec.).\033[K\n",
+           printf (" (%d files/sec.)",
                    (int) (state->processed_files / elapsed));
-       else
-           printf (".\033[K\n");
+       printf (".%s\n", (state->output_is_a_tty) ? "\033[K" : "");
     }
 
     if (state->added_messages)
@@ -910,7 +931,11 @@ int
 notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
 {
     notmuch_database_t *notmuch;
-    add_files_state_t add_files_state;
+    add_files_state_t add_files_state = {
+       .verbosity = VERBOSITY_NORMAL,
+       .debug = FALSE,
+       .output_is_a_tty = isatty (fileno (stdout)),
+    };
     struct timeval tv_start;
     int ret = 0;
     struct stat st;
@@ -925,15 +950,12 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
     notmuch_bool_t quiet = FALSE, verbose = FALSE;
     notmuch_status_t status;
 
-    add_files_state.verbosity = VERBOSITY_NORMAL;
-    add_files_state.debug = FALSE;
-    add_files_state.output_is_a_tty = isatty (fileno (stdout));
-
     notmuch_opt_desc_t options[] = {
        { NOTMUCH_OPT_BOOLEAN,  &quiet, "quiet", 'q', 0 },
        { NOTMUCH_OPT_BOOLEAN,  &verbose, "verbose", 'v', 0 },
        { NOTMUCH_OPT_BOOLEAN,  &add_files_state.debug, "debug", 'd', 0 },
        { NOTMUCH_OPT_BOOLEAN,  &no_hooks, "no-hooks", 'n', 0 },
+       { NOTMUCH_OPT_INHERIT, (void *) &notmuch_shared_options, NULL, 0, 0 },
        { 0, 0, 0, 0, 0 }
     };
 
@@ -941,6 +963,8 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
     if (opt_index < 0)
        return EXIT_FAILURE;
 
+    notmuch_process_shared_options (argv[0]);
+
     /* quiet trumps verbose */
     if (quiet)
        add_files_state.verbosity = VERBOSITY_QUIET;
@@ -985,9 +1009,17 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
            return EXIT_FAILURE;
        add_files_state.total_files = count;
     } else {
-       if (notmuch_database_open (db_path, NOTMUCH_DATABASE_MODE_READ_WRITE,
-                                  &notmuch))
+       char *status_string = NULL;
+       if (notmuch_database_open_verbose (db_path, NOTMUCH_DATABASE_MODE_READ_WRITE,
+                                          &notmuch, &status_string)) {
+           if (status_string) {
+               fputs (status_string, stderr);
+               free (status_string);
+           }
            return EXIT_FAILURE;
+       }
+
+       notmuch_exit_if_unmatched_db_uuid (notmuch);
 
        if (notmuch_database_needs_upgrade (notmuch)) {
            time_t now = time (NULL);
@@ -1014,7 +1046,7 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
            }
 
            if (notmuch_database_dump (notmuch, backup_name, "",
-                                      DUMP_FORMAT_BATCH_TAG, TRUE)) {
+                                      DUMP_FORMAT_BATCH_TAG, DUMP_INCLUDE_DEFAULT, TRUE)) {
                fprintf (stderr, "Backup failed. Aborting upgrade.");
                return EXIT_FAILURE;
            }
@@ -1040,7 +1072,7 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
     if (notmuch == NULL)
        return EXIT_FAILURE;
 
-    /* Setup our handler for SIGINT. We do this after having
+    /* Set up our handler for SIGINT. We do this after having
      * potentially done a database upgrade we this interrupt handler
      * won't support. */
     memset (&action, 0, sizeof (struct sigaction));
@@ -1052,9 +1084,6 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
     talloc_free (dot_notmuch_path);
     dot_notmuch_path = NULL;
 
-    add_files_state.processed_files = 0;
-    add_files_state.added_messages = 0;
-    add_files_state.removed_messages = add_files_state.renamed_messages = 0;
     gettimeofday (&add_files_state.tv_start, NULL);
 
     add_files_state.removed_files = _filename_list_create (config);
@@ -1126,5 +1155,11 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
     if (!no_hooks && !ret && !interrupted)
        ret = notmuch_run_hook (db_path, "post-new");
 
-    return ret || interrupted ? EXIT_FAILURE : EXIT_SUCCESS;
+    if (ret || interrupted)
+       return EXIT_FAILURE;
+
+    if (add_files_state.vanished_files)
+       return NOTMUCH_EXIT_TEMPFAIL;
+
+    return EXIT_SUCCESS;
 }