]> git.notmuchmail.org Git - notmuch/blobdiff - notmuch.c
cli: try to run external notmuch- prefixed commands as subcommands
[notmuch] / notmuch.c
index c528dce2d12100b66d9dffd00093faefd33f5965..b9c320329dd526000b436210d52cceee0ced0717 100644 (file)
--- a/notmuch.c
+++ b/notmuch.c
@@ -14,7 +14,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/ .
  *
  * Authors: Carl Worth <cworth@cworth.org>
  *         Keith Packard <keithp@keithp.com>
@@ -47,10 +47,12 @@ static int
 _help_for (const char *topic);
 
 static notmuch_bool_t print_version = FALSE, print_help = FALSE;
+char *notmuch_requested_db_uuid = NULL;
 
 const notmuch_opt_desc_t notmuch_shared_options [] = {
     { NOTMUCH_OPT_BOOLEAN, &print_version, "version", 'v', 0 },
     { NOTMUCH_OPT_BOOLEAN, &print_help, "help", 'h', 0 },
+    { NOTMUCH_OPT_STRING, &notmuch_requested_db_uuid, "uuid", 'u', 0 },
     {0, 0, 0, 0, 0}
 };
 
@@ -218,6 +220,22 @@ be supported in the future.\n", notmuch_format_version);
     }
 }
 
+void
+notmuch_exit_if_unmatched_db_uuid (notmuch_database_t *notmuch)
+{
+    const char *uuid = NULL;
+
+    if (!notmuch_requested_db_uuid)
+       return;
+    IGNORE_RESULT (notmuch_database_get_revision (notmuch, &uuid));
+
+    if (strcmp (notmuch_requested_db_uuid, uuid) != 0){
+       fprintf (stderr, "Error: requested database revision %s does not match %s\n",
+                notmuch_requested_db_uuid, uuid);
+       exit (1);
+    }
+}
+
 static void
 exec_man (const char *page)
 {
@@ -336,7 +354,7 @@ notmuch_command (notmuch_config_t *config,
            "You can also use \"notmuch show\" with any of the thread IDs resulting\n"
            "from a search. Finally, you may want to explore using a more sophisticated\n"
            "interface to notmuch such as the emacs interface implemented in notmuch.el\n"
-           "or any other interface described at http://notmuchmail.org\n\n"
+           "or any other interface described at https://notmuchmail.org\n\n"
            "And don't forget to run \"notmuch new\" whenever new mail arrives.\n\n"
            "Have fun, and may your inbox never have much mail.\n\n",
            notmuch_config_get_user_name (config),
@@ -345,6 +363,39 @@ notmuch_command (notmuch_config_t *config,
     return EXIT_SUCCESS;
 }
 
+/*
+ * Try to run subcommand in argv[0] as notmuch- prefixed external
+ * command. argv must be NULL terminated (argv passed to main always
+ * is).
+ *
+ * Does not return if the external command is found and
+ * executed. Return TRUE if external command is not found. Return
+ * FALSE on errors.
+ */
+static notmuch_bool_t try_external_command(char *argv[])
+{
+    char *old_argv0 = argv[0];
+    notmuch_bool_t ret = TRUE;
+
+    argv[0] = talloc_asprintf (NULL, "notmuch-%s", old_argv0);
+
+    /*
+     * This will only return on errors. Not finding an external
+     * command (ENOENT) is not an error from our perspective.
+     */
+    execvp (argv[0], argv);
+    if (errno != ENOENT) {
+       fprintf (stderr, "Error: Running external command '%s' failed: %s\n",
+                argv[0], strerror(errno));
+       ret = FALSE;
+    }
+
+    talloc_free (argv[0]);
+    argv[0] = old_argv0;
+
+    return ret;
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -381,15 +432,17 @@ main (int argc, char *argv[])
        goto DONE;
     }
 
-    notmuch_process_shared_options (NULL);
-
     if (opt_index < argc)
        command_name = argv[opt_index];
 
+    notmuch_process_shared_options (command_name);
+
     command = find_command (command_name);
     if (!command) {
-       fprintf (stderr, "Error: Unknown command '%s' (see \"notmuch help\")\n",
-                command_name);
+       /* This won't return if the external command is found. */
+       if (try_external_command(argv + opt_index))
+           fprintf (stderr, "Error: Unknown command '%s' (see \"notmuch help\")\n",
+                    command_name);
        ret = EXIT_FAILURE;
        goto DONE;
     }