unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
* [PATCH 0/2] Notmuch cat v2
@ 2010-10-22  9:28 Michal Sojka
  2010-10-22  9:28 ` [PATCH 1/2] Add 'cat' subcommand Michal Sojka
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Michal Sojka @ 2010-10-22  9:28 UTC (permalink / raw)
  To: notmuch

Hi all,

this is my second attempt to implement notmuch cat subcommand (the
first version was posted in
id:1271747793-17507-1-git-send-email-sojkam1@fel.cvut.cz). This
subcommand outputs the given message to stdout.

In this version the arguments are classical notmuch search terms and
not a filename as in the previous version. Emacs interface then uses
message-id to retrieve the message.

Some people suggested that cat could be implemented as a special
format of show subcommand. That would be possible, but it seems that
show command always constructs threads form the messages which means
that is executes several database queries. I consider this as
unnecessary overhead and for that reason cat is a separate subcommand.

Michal Sojka (2):
  Add 'cat' subcommand
  emacs: Access raw messages via cat subcommand

 emacs/notmuch-show.el |   14 +++++---
 notmuch-client.h      |    3 ++
 notmuch-show.c        |   83 +++++++++++++++++++++++++++++++++++++++++++++++++
 notmuch.1             |    4 ++
 notmuch.c             |    4 ++
 test/cat              |   38 ++++++++++++++++++++++
 test/notmuch-test     |    2 +-
 7 files changed, 142 insertions(+), 6 deletions(-)
 create mode 100755 test/cat

-- 
1.7.2.3

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] Add 'cat' subcommand
  2010-10-22  9:28 [PATCH 0/2] Notmuch cat v2 Michal Sojka
@ 2010-10-22  9:28 ` Michal Sojka
  2010-10-22  9:28 ` [PATCH 2/2] emacs: Access raw messages via cat subcommand Michal Sojka
  2010-11-04 19:25 ` [PATCH 0/2] Notmuch cat v2 Carl Worth
  2 siblings, 0 replies; 4+ messages in thread
From: Michal Sojka @ 2010-10-22  9:28 UTC (permalink / raw)
  To: notmuch

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@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)"
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

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] emacs: Access raw messages via cat subcommand
  2010-10-22  9:28 [PATCH 0/2] Notmuch cat v2 Michal Sojka
  2010-10-22  9:28 ` [PATCH 1/2] Add 'cat' subcommand Michal Sojka
@ 2010-10-22  9:28 ` Michal Sojka
  2010-11-04 19:25 ` [PATCH 0/2] Notmuch cat v2 Carl Worth
  2 siblings, 0 replies; 4+ messages in thread
From: Michal Sojka @ 2010-10-22  9:28 UTC (permalink / raw)
  To: notmuch

This patch modifies the following commands to access the messages via
cat subcommand:
- view/save attachments ('v', 'w'),
- view a raw message ('V') and
- pipe a message to a command ('|').

With this patch, it is straightforward to use notmuch emacs interface
with a remote database accessed over SSH. To do this, it is sufficient
to redefine notmuch-command variable to contain the name of a script
containing:

    ssh user@host notmuch "$@"

If the ssh client has enabled connection sharing (ControlMaster option
in OpenSSH), the emacs interface is almost as responsive as when
notmuch is invoked locally.
---
 emacs/notmuch-show.el |   14 +++++++++-----
 1 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 98d25ef..5d207b9 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -85,10 +85,10 @@ any given message."
 (defmacro with-current-notmuch-show-message (&rest body)
   "Evaluate body with current buffer set to the text of current message"
   `(save-excursion
-     (let ((filename (notmuch-show-get-filename)))
-       (let ((buf (generate-new-buffer (concat "*notmuch-msg-" filename "*"))))
+     (let ((id (notmuch-show-get-message-id)))
+       (let ((buf (generate-new-buffer (concat "*notmuch-msg-" id "*"))))
          (with-current-buffer buf
-           (insert-file-contents filename nil nil nil t)
+	    (call-process notmuch-command nil t nil "cat" id)
            ,@body)
 	 (kill-buffer buf)))))
 
@@ -918,7 +918,11 @@ any effects from previous calls to
 (defun notmuch-show-view-raw-message ()
   "View the file holding the current message."
   (interactive)
-  (view-file (notmuch-show-get-filename)))
+  (let ((id (notmuch-show-get-message-id)))
+    (let ((buf (get-buffer-create (concat "*notmuch-raw-" id "*"))))
+      (switch-to-buffer buf)
+      (save-excursion
+	(call-process notmuch-command nil t nil "cat" id)))))
 
 (defun notmuch-show-pipe-message (entire-thread command)
   "Pipe the contents of the current message (or thread) to the given command.
@@ -939,7 +943,7 @@ than only the current message."
 		       (mapconcat 'identity (notmuch-show-get-message-ids-for-open-messages) " OR "))
 		      " | " command))
       (setq shell-command
-	    (concat command " < " (shell-quote-argument (notmuch-show-get-filename)))))
+	    (concat "notmuch cat " (shell-quote-argument (notmuch-show-get-message-id)) " | " command)))
     (start-process-shell-command "notmuch-pipe-command" "*notmuch-pipe*" shell-command)))
 
 (defun notmuch-show-add-tag (&rest toadd)
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] Notmuch cat v2
  2010-10-22  9:28 [PATCH 0/2] Notmuch cat v2 Michal Sojka
  2010-10-22  9:28 ` [PATCH 1/2] Add 'cat' subcommand Michal Sojka
  2010-10-22  9:28 ` [PATCH 2/2] emacs: Access raw messages via cat subcommand Michal Sojka
@ 2010-11-04 19:25 ` Carl Worth
  2 siblings, 0 replies; 4+ messages in thread
From: Carl Worth @ 2010-11-04 19:25 UTC (permalink / raw)
  To: Michal Sojka, notmuch

[-- Attachment #1: Type: text/plain, Size: 2206 bytes --]

On Fri, 22 Oct 2010 11:28:02 +0200, Michal Sojka <sojkam1@fel.cvut.cz> wrote:
> this is my second attempt to implement notmuch cat subcommand (the
> first version was posted in
> id:1271747793-17507-1-git-send-email-sojkam1@fel.cvut.cz). This
> subcommand outputs the given message to stdout.

Hi Michal,

I'm *really* excited about this feature. The ability to more easily use
notmuch over ssh is really appealing, and as I mentioned previously, I
see this patch as a prerequisite for the maildir-synchronization work.

> In this version the arguments are classical notmuch search terms and
> not a filename as in the previous version. Emacs interface then uses
> message-id to retrieve the message.

Excellent. This is much better than before.

> Some people suggested that cat could be implemented as a special
> format of show subcommand. That would be possible, but it seems that
> show command always constructs threads form the messages which means
> that is executes several database queries. I consider this as
> unnecessary overhead and for that reason cat is a separate subcommand.

So I'll argue for "notmuch show --format=raw" here.

You're correct that the current implementation of "notmuch show" calls
notmuch_database_search_threads and --format=raw doesn't need to or want
to do that. But see, for example, recent notmuch-search.c and you'll see
that depending on the --output option, the "notmuch search" command will
sometimes call search_threads and will sometimes call
search_messages. So I think we want the same thing here.

Meanwhile, since this command is only acting on the first message
matched, don't you think it should be documented as only working with a
search term that matches a single message? Then it could simply print an
error message if the terms matched multiple messages.[*]

-Carl

[*] And we'll want that same behavior for "notmuch part" as well. That's
already implemented in notmuch-show.c and should also be implemented as
a sub-option of "notmuch show" I think, (which is probably another
outstanding patch for me to review). So there might be room for a little
code-sharing there.

-- 
carl.d.worth@intel.com

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-11-04 19:26 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-22  9:28 [PATCH 0/2] Notmuch cat v2 Michal Sojka
2010-10-22  9:28 ` [PATCH 1/2] Add 'cat' subcommand Michal Sojka
2010-10-22  9:28 ` [PATCH 2/2] emacs: Access raw messages via cat subcommand Michal Sojka
2010-11-04 19:25 ` [PATCH 0/2] Notmuch cat v2 Carl Worth

Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).