Add 'cat' subcommand
authorMichal Sojka <sojkam1@fel.cvut.cz>
Fri, 22 Oct 2010 09:28:03 +0000 (11:28 +0200)
committerCarl Worth <cworth@cworth.org>
Sat, 6 Nov 2010 00:51:18 +0000 (17:51 -0700)
This command outputs a raw message matched by search term to the
standard output. It allows MUAs to access the messages for piping,
attachment manipulation, etc. by running notmuch cat rather then
directly access the file. This will simplify the MUAs when they need
to operate on a remote database.

Edited-by: Carl Worth <cworth@cworth.org>: Remove trailing whitespace,
add missing "test_done" to new test script to avoid "Unexpected exit"
error.

notmuch-client.h
notmuch-show.c
notmuch.1
notmuch.c
test/cat [new file with mode: 0755]
test/notmuch-test

index d530578ad9bd0dc8cfe2dc328c25dc86ac09efd2..fdfb94ad59879a4269c0cb3b7e4c2cd382e0cdf6 100644 (file)
@@ -110,6 +110,9 @@ notmuch_tag_command (void *ctx, int argc, char *argv[]);
 int
 notmuch_search_tags_command (void *ctx, int argc, char *argv[]);
 
+int
+notmuch_cat_command (void *ctx, int argc, char *argv[]);
+
 int
 notmuch_part_command (void *ctx, int argc, char *argv[]);
 
index ea465dec7aa65e7385dd8b3e2170da1c1f79d2a7..f46e0c8218785efb77957fffa048c0d1c0956f87 100644 (file)
@@ -631,6 +631,89 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
     return 0;
 }
 
+int
+notmuch_cat_command (void *ctx, unused (int argc), unused (char *argv[]))
+{
+    notmuch_config_t *config;
+    notmuch_database_t *notmuch;
+    notmuch_query_t *query;
+    notmuch_messages_t *messages;
+    notmuch_message_t *message;
+    char *query_string;
+    int i;
+    const char *filename;
+    FILE *file;
+    size_t size;
+    char buf[4096];
+
+    for (i = 0; i < argc && argv[i][0] == '-'; i++) {
+       fprintf (stderr, "Unrecognized option: %s\n", argv[i]);
+       return 1;
+    }
+
+    config = notmuch_config_open (ctx, NULL, NULL);
+    if (config == NULL)
+       return 1;
+
+    query_string = query_string_from_args (ctx, argc, argv);
+    if (query_string == NULL) {
+       fprintf (stderr, "Out of memory\n");
+       return 1;
+    }
+
+    if (*query_string == '\0') {
+       fprintf (stderr, "Error: notmuch cat requires at least one search term.\n");
+       return 1;
+    }
+
+    notmuch = notmuch_database_open (notmuch_config_get_database_path (config),
+                                    NOTMUCH_DATABASE_MODE_READ_ONLY);
+    if (notmuch == NULL)
+       return 1;
+
+    query = notmuch_query_create (notmuch, query_string);
+    if (query == NULL) {
+       fprintf (stderr, "Error: Out of memory\n");
+       return 1;
+    }
+
+    if (notmuch_query_count_messages (query) != 1) {
+       fprintf (stderr, "Error: search term did not match precisely one message.\n");
+       return 1;
+    }
+
+    messages = notmuch_query_search_messages (query);
+    message = notmuch_messages_get (messages);
+
+    if (message == NULL) {
+       fprintf (stderr, "Error: Cannot find matching message.\n");
+       return 1;
+    }
+
+    filename = notmuch_message_get_filename (message);
+    if (filename == NULL) {
+       fprintf (stderr, "Error: Cannot message filename.\n");
+       return 1;
+    }
+
+    file = fopen (filename, "r");
+    if (file == NULL) {
+       fprintf (stderr, "Error: Cannot open file %s: %s\n", filename, strerror (errno));
+       return 1;
+    }
+
+    while (!feof (file)) {
+       size = fread (buf, 1, sizeof (buf), file);
+       fwrite (buf, size, 1, stdout);
+    }
+
+    fclose (file);
+    notmuch_query_destroy (query);
+    notmuch_database_close (notmuch);
+
+    return 0;
+}
+
 int
 notmuch_part_command (void *ctx, unused (int argc), unused (char *argv[]))
 {
index e4eed60fc95e5f828f940b4efda1a094f34c3180..853b5eafab31cac83959e074713174f528d6475a 100644 (file)
--- a/notmuch.1
+++ b/notmuch.1
@@ -300,6 +300,10 @@ See the
 section below for details of the supported syntax for <search-terms>.
 .RE
 .TP
+.BR cat  " <search-term>..."
+
+Output raw content of a single message matched by the search term.
+.TP
 .BR count " <search-term>..."
 
 Count messages matching the search terms.
index 030e49429f6ed529c92a843b965179cc91fd19a8..0eba89a38e30f48d20c67ef0d6b6ef8ba104ac20 100644 (file)
--- a/notmuch.c
+++ b/notmuch.c
@@ -343,6 +343,10 @@ command_t commands[] = {
       "\tcontain tags only from messages that match the search-term(s).\n"
       "\n"
       "\tIn both cases the list will be alphabetically sorted." },
+    { "cat", notmuch_cat_command,
+      "<search-terms>",
+      "Output raw content of a single message matched by the search term.",
+      "" },
     { "part", notmuch_part_command,
       "--part=<num> <search-terms>",
       "Output a single MIME part of a message.",
diff --git a/test/cat b/test/cat
new file mode 100755 (executable)
index 0000000..c2cfedb
--- /dev/null
+++ b/test/cat
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+test_description='notmuch cat'
+. ./test-lib.sh
+
+test_begin_subtest "Generate some messages"
+generate_message
+generate_message
+output=$(NOTMUCH_NEW)
+test_expect_equal "$output" "Added 2 new messages to the database."
+
+test_begin_subtest "Without arguments"
+output=$(notmuch cat 2>&1)
+test_expect_equal "$output" "Error: notmuch cat requires at least one search term."
+
+test_begin_subtest "Attempt to cat multiple messages"
+output=$(notmuch cat "*" 2>&1)
+test_expect_equal "$output" "Error: search term did not match precisely one message."
+
+test_begin_subtest "Cat a message"
+output=$(notmuch cat id:msg-001@notmuch-test-suite)
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Message-Id: <msg-001@notmuch-test-suite>
+Subject: Test message #1
+Date: Tue, 05 Jan 2001 15:43:57 -0000
+
+This is just a test message (#1)"
+
+test_begin_subtest "Cat another message"
+output=$(notmuch cat id:msg-002@notmuch-test-suite)
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Notmuch Test Suite <test_suite@notmuchmail.org>
+Message-Id: <msg-002@notmuch-test-suite>
+Subject: Test message #2
+Date: Tue, 05 Jan 2001 15:43:57 -0000
+
+This is just a test message (#2)"
+
+test_done
index 60c3ecbcbe9968ac0dcd5fe2798a32ff6ec5cbf0..6b89409060c3f80d0deeaecacc4701019e694414 100755 (executable)
@@ -16,7 +16,7 @@ fi
 
 cd $(dirname "$0")
 
-TESTS="basic new search json thread-naming reply dump-restore uuencode thread-order author-order from-guessing long-id encoding emacs"
+TESTS="basic new search json thread-naming reply cat dump-restore uuencode thread-order author-order from-guessing long-id encoding emacs"
 
 # Clean up any results from a previous run
 rm -r test-results >/dev/null 2>/dev/null