[PATCH 1/2] Add 'cat' subcommand

Michal Sojka sojkam1 at fel.cvut.cz
Fri Oct 22 02:28:03 PDT 2010


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.
---
 notmuch-client.h  |    3 ++
 notmuch-show.c    |   83 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 notmuch.1         |    4 ++
 notmuch.c         |    4 ++
 test/cat          |   38 ++++++++++++++++++++++++
 test/notmuch-test |    2 +-
 6 files changed, 133 insertions(+), 1 deletions(-)
 create mode 100755 test/cat

diff --git a/notmuch-client.h b/notmuch-client.h
index 20be43b..82526f8 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -111,6 +111,9 @@ 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[]);
 
 const char *
diff --git a/notmuch-show.c b/notmuch-show.c
index ea465de..285f38f 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -632,6 +632,89 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
 }
 
 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[]))
 {
 	notmuch_config_t *config;
diff --git a/notmuch.1 b/notmuch.1
index 3ec9c55..2ec4048 100644
--- a/notmuch.1
+++ b/notmuch.1
@@ -255,6 +255,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.
diff --git a/notmuch.c b/notmuch.c
index f6b8c13..e36486c 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -310,6 +310,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
index 0000000..c6cefea
--- /dev/null
+++ b/test/cat
@@ -0,0 +1,38 @@
+#!/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 at notmuch-test-suite)
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite at notmuchmail.org>
+To: Notmuch Test Suite <test_suite at notmuchmail.org>
+Message-Id: <msg-001 at 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 at notmuch-test-suite)
+test_expect_equal "$output" "From: Notmuch Test Suite <test_suite at notmuchmail.org>
+To: Notmuch Test Suite <test_suite at notmuchmail.org>
+Message-Id: <msg-002 at notmuch-test-suite>
+Subject: Test message #2
+Date: Tue, 05 Jan 2001 15:43:57 -0000
+
+This is just a test message (#2)"
diff --git a/test/notmuch-test b/test/notmuch-test
index 13c5d80..0c33a47 100755
--- a/test/notmuch-test
+++ b/test/notmuch-test
@@ -8,7 +8,7 @@
 
 cd $(dirname "$0")
 
-TESTS="basic new search json thread-naming reply dump-restore uuencode thread-order author-order from-guessing long-id encoding"
+TESTS="basic new search json thread-naming reply dump-restore uuencode thread-order author-order from-guessing long-id encoding cat"
 
 # Clean up any results from a previous run
 rm -r test-results >/dev/null 2>/dev/null
-- 
1.7.2.3



More information about the notmuch mailing list