*/
#include "notmuch-client.h"
+#include "tag-util.h"
#include <unistd.h>
char *abspath;
int err, saved_errno;
-#ifdef _DIRENT_HAVE_D_TYPE
+#if HAVE_D_TYPE
/* Mapping from d_type to stat mode_t. We omit DT_LNK so that
* we'll fall through to stat and get the real file type. */
static const mode_t modes[] = {
*/
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;
}
/* 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;
}
"%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);
{
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);
}
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);
"%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);
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);
goto DONE;
}
+ status = notmuch_directory_delete (directory);
+
DONE:
- notmuch_directory_destroy (directory);
+ if (status)
+ notmuch_directory_destroy (directory);
return status;
}
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;
struct sigaction action;
_filename_node_t *f;
int opt_index;
- int i;
+ unsigned int i;
notmuch_bool_t timer_is_active = FALSE;
notmuch_bool_t no_hooks = FALSE;
notmuch_bool_t quiet = FALSE, verbose = FALSE;
-
- add_files_state.verbosity = VERBOSITY_NORMAL;
- add_files_state.debug = FALSE;
- add_files_state.output_is_a_tty = isatty (fileno (stdout));
+ notmuch_status_t status;
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 *) ¬much_shared_options, NULL, 0, 0 },
{ 0, 0, 0, 0, 0 }
};
if (opt_index < 0)
return EXIT_FAILURE;
+ notmuch_process_shared_options (argv[0]);
+
/* quiet trumps verbose */
if (quiet)
add_files_state.verbosity = VERBOSITY_QUIET;
add_files_state.synchronize_flags = notmuch_config_get_maildir_synchronize_flags (config);
db_path = notmuch_config_get_database_path (config);
+ for (i = 0; i < add_files_state.new_tags_length; i++) {
+ const char *error_msg;
+
+ error_msg = illegal_tag (add_files_state.new_tags[i], FALSE);
+ if (error_msg) {
+ fprintf (stderr, "Error: tag '%s' in new.tags: %s\n",
+ add_files_state.new_tags[i], error_msg);
+ return EXIT_FAILURE;
+ }
+ }
+
if (!no_hooks) {
ret = notmuch_run_hook (db_path, "pre-new");
if (ret)
return EXIT_FAILURE;
add_files_state.total_files = count;
} else {
- if (notmuch_database_open (db_path, NOTMUCH_DATABASE_MODE_READ_WRITE,
- ¬much))
+ char *status_string = NULL;
+ if (notmuch_database_open_verbose (db_path, NOTMUCH_DATABASE_MODE_READ_WRITE,
+ ¬much, &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)) {
- if (add_files_state.verbosity >= VERBOSITY_NORMAL)
+ time_t now = time (NULL);
+ struct tm *gm_time = gmtime (&now);
+
+ /* since dump files are written atomically, the amount of
+ * harm from overwriting one within a second seems
+ * relatively small. */
+
+ const char *backup_name =
+ talloc_asprintf (notmuch, "%s/dump-%04d%02d%02dT%02d%02d%02d.gz",
+ dot_notmuch_path,
+ gm_time->tm_year + 1900,
+ gm_time->tm_mon + 1,
+ gm_time->tm_mday,
+ gm_time->tm_hour,
+ gm_time->tm_min,
+ gm_time->tm_sec);
+
+ if (add_files_state.verbosity >= VERBOSITY_NORMAL) {
printf ("Welcome to a new version of notmuch! Your database will now be upgraded.\n");
+ printf ("This process is safe to interrupt.\n");
+ printf ("Backing up tags to %s...\n", backup_name);
+ }
+
+ if (notmuch_database_dump (notmuch, backup_name, "",
+ DUMP_FORMAT_BATCH_TAG, TRUE)) {
+ fprintf (stderr, "Backup failed. Aborting upgrade.");
+ return EXIT_FAILURE;
+ }
+
gettimeofday (&add_files_state.tv_start, NULL);
- notmuch_database_upgrade (notmuch,
- add_files_state.verbosity >= VERBOSITY_NORMAL ? upgrade_print_progress : NULL,
- &add_files_state);
+ status = notmuch_database_upgrade (
+ notmuch,
+ add_files_state.verbosity >= VERBOSITY_NORMAL ? upgrade_print_progress : NULL,
+ &add_files_state);
+ if (status) {
+ printf ("Upgrade failed: %s\n",
+ notmuch_status_to_string (status));
+ notmuch_database_destroy (notmuch);
+ return EXIT_FAILURE;
+ }
if (add_files_state.verbosity >= VERBOSITY_NORMAL)
- printf ("Your notmuch database has now been upgraded to database format version %u.\n",
- notmuch_database_get_version (notmuch));
+ printf ("Your notmuch database has now been upgraded.\n");
}
add_files_state.total_files = 0;
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));
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);
}
for (f = add_files_state.directory_mtimes->head; f && !interrupted; f = f->next) {
- notmuch_status_t status;
notmuch_directory_t *directory;
status = notmuch_database_get_directory (notmuch, f->filename, &directory);
if (status == NOTMUCH_STATUS_SUCCESS && directory) {