[PATCH] notmuch-tag: initialize with enum instead of 0.

2013-01-19 Thread Tomi Ollila
On Sat, Jan 19 2013, david at tethera.net wrote:

> From: David Bremner 
>
> This is just a cosmetic fix to make the "type" of ret more clear.
> ---
>  notmuch-tag.c |2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/notmuch-tag.c b/notmuch-tag.c
> index b54c55d..d9daf8f 100644
> --- a/notmuch-tag.c
> +++ b/notmuch-tag.c
> @@ -97,7 +97,7 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const 
> char *query_string,
>  notmuch_query_t *query;
>  notmuch_messages_t *messages;
>  notmuch_message_t *message;
> -int ret = 0;
> +int ret = NOTMUCH_STATUS_SUCCESS;

LGTM.

Tomi


[PATCH] notmuch-tag: initialize with enum instead of 0.

2013-01-19 Thread David Bremner
david at tethera.net writes:

> From: David Bremner 
>
> This is just a cosmetic fix to make the "type" of ret more clear.

Pushed. I even caught the '.' and the end of the commit subject.
No idea why that is so hard for me.

d


[PATCH 1/1] devel/release-checks.sh: version string problem does not halt execution

2013-01-19 Thread David Bremner
Tomi Ollila  writes:

> Version string has strict format requirements in release-check.sh:
> only numbers and periods (in sane order) are accepted.
> Mismatch there used to halt further execution.
> In this case, checking versions like '*~rc1' for (more) problems
> was not possible.
> This 'fatal error' is now changed buffered error message like in
> following tests, and is displayed at the end of execution.

pushed. That's probably good enough, given the small userbase of this
script.

d


[PATCH 7/7] CLI: add simple error handling for talloc logging

2013-01-19 Thread da...@tethera.net
From: David Bremner 

This really should have been there before. I think it's better to do
the actual operation and then possibly fail writing the memory log,
but it would not be too hard to change it to abort earlier.
---
 notmuch.c |7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/notmuch.c b/notmuch.c
index f8d4b35..c3336e8 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -301,7 +301,12 @@ main (int argc, char *argv[])

if (leak_report && (strcmp (leak_report, "") != 0)) {
FILE *report = fopen (leak_report, "w");
-   talloc_report_full (NULL, report);
+   if (report) {
+   talloc_report_full (NULL, report);
+   } else {
+   ret = 1;
+   perror (leak_report);
+   }
}

return ret;
-- 
1.7.10.4



[PATCH 6/7] man: document NOTMUCH_TALLOC_REPORT environment variable

2013-01-19 Thread da...@tethera.net
From: David Bremner 

---
 man/man1/notmuch.1 |7 +++
 1 file changed, 7 insertions(+)

diff --git a/man/man1/notmuch.1 b/man/man1/notmuch.1
index 5c58c41..391eb88 100644
--- a/man/man1/notmuch.1
+++ b/man/man1/notmuch.1
@@ -155,6 +155,13 @@ behavior of notmuch.
 .B NOTMUCH_CONFIG
 Specifies the location of the notmuch configuration file. Notmuch will
 use ${HOME}/.notmuch\-config if this variable is not set.
+
+.TP
+.B NOTMUCH_TALLOC_REPORT
+Location to write a talloc memory usage report. Overridden by the
+.B --leak-report
+option.
+
 .SH SEE ALSO

 \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1),
-- 
1.7.10.4



[PATCH 5/7] CLI: add --leak-report top level option

2013-01-19 Thread da...@tethera.net
From: David Bremner 

This roughly mimics the samba4 argument. The presence of the command
line argument overrides any value of NOTMUCH_TALLOC_REPORT in the
environment.
---
 man/man1/notmuch.1 |8 
 notmuch.c  |   18 +++---
 2 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/man/man1/notmuch.1 b/man/man1/notmuch.1
index 6bf9b2e..5c58c41 100644
--- a/man/man1/notmuch.1
+++ b/man/man1/notmuch.1
@@ -70,6 +70,14 @@ Print a synopsis of available commands and exit.
 Print the installed version of notmuch, and exit.
 .RE

+.RS 4
+.TP 4
+.BI \-\-leak-report= path
+
+Write a detailed report of all memory allocated via talloc to
+.I path
+.RE
+
 .SH COMMANDS


diff --git a/notmuch.c b/notmuch.c
index a674481..f8d4b35 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -250,11 +250,13 @@ main (int argc, char *argv[])
 command_t *command;
 unsigned int i;
 notmuch_bool_t print_help=FALSE, print_version=FALSE;
+const char* leak_report=NULL;
 int opt_index;

 notmuch_opt_desc_t options[] = {
{ NOTMUCH_OPT_BOOLEAN, _help, "help", 'h', 0 },
{ NOTMUCH_OPT_BOOLEAN, _version, "version", 'v', 0 },
+   { NOTMUCH_OPT_STRING, _report, "leak-report", 'l', 0 },
{ 0, 0, 0, 0, 0 }
 };

@@ -290,21 +292,15 @@ main (int argc, char *argv[])

if (strcmp (argv[opt_index], command->name) == 0) {
int ret;
-   char *talloc_report;

ret = (command->function)(local, argc - opt_index, argv + 
opt_index);

-   /* in the future support for this environment variable may
-* be supplemented or replaced by command line arguments
-* --leak-report and/or --leak-report-full */
-
-   talloc_report = getenv ("NOTMUCH_TALLOC_REPORT");
-
-   /* this relies on the previous call to
-* talloc_enable_null_tracking */
+   if (leak_report == NULL) {
+   leak_report = getenv ("NOTMUCH_TALLOC_REPORT");
+   }

-   if (talloc_report && strcmp (talloc_report, "") != 0) {
-   FILE *report = fopen (talloc_report, "w");
+   if (leak_report && (strcmp (leak_report, "") != 0)) {
+   FILE *report = fopen (leak_report, "w");
talloc_report_full (NULL, report);
}

-- 
1.7.10.4



[PATCH 4/7] man: document existing top level options

2013-01-19 Thread da...@tethera.net
From: David Bremner 

The options --help and --version were not documented before.  One
could quibble about how useful that documentation is, but we will soon
add more options.
---
 man/man1/notmuch.1 |   22 +-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/man/man1/notmuch.1 b/man/man1/notmuch.1
index 69805cb..6bf9b2e 100644
--- a/man/man1/notmuch.1
+++ b/man/man1/notmuch.1
@@ -21,7 +21,7 @@
 notmuch \- thread-based email index, search, and tagging
 .SH SYNOPSIS
 .B notmuch
-.IR command " [" args " ...]"
+.RI "[" option " ...] " command  " [" arg " ...]"
 .SH DESCRIPTION
 Notmuch is a command-line based program for indexing, searching,
 reading, and tagging large collections of email messages.
@@ -50,6 +50,26 @@ interfaces to notmuch. The emacs-based interface to notmuch 
(available under
 in the Notmuch source distribution) is probably the most widely used at
 this time.

+.SH OPTIONS
+
+Supported global options for
+.B notmuch
+include
+
+.RS 4
+.TP 4
+.B \-\-help
+
+Print a synopsis of available commands and exit.
+.RE
+
+.RS 4
+.TP 4
+.B \-\-version
+
+Print the installed version of notmuch, and exit.
+.RE
+
 .SH COMMANDS


-- 
1.7.10.4



[PATCH 3/7] CLI: convert top level argument parsing to use command-line-arguments

2013-01-19 Thread da...@tethera.net
From: David Bremner 

This isn't really a win for conciseness yet, but will make it easier
to add options.
---
 notmuch.c |   22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/notmuch.c b/notmuch.c
index f13fd27..a674481 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -249,6 +249,14 @@ main (int argc, char *argv[])
 void *local;
 command_t *command;
 unsigned int i;
+notmuch_bool_t print_help=FALSE, print_version=FALSE;
+int opt_index;
+
+notmuch_opt_desc_t options[] = {
+   { NOTMUCH_OPT_BOOLEAN, _help, "help", 'h', 0 },
+   { NOTMUCH_OPT_BOOLEAN, _version, "version", 'v', 0 },
+   { 0, 0, 0, 0, 0 }
+};

 talloc_enable_null_tracking ();

@@ -263,10 +271,16 @@ main (int argc, char *argv[])
 if (argc == 1)
return notmuch (local);

-if (strcmp (argv[1], "--help") == 0)
+opt_index = parse_arguments (argc, argv, options, 1);
+if (opt_index < 0) {
+   /* diagnostics already printed */
+   return 1;
+}
+
+if (print_help)
return notmuch_help_command (NULL, argc - 1, [1]);

-if (strcmp (argv[1], "--version") == 0) {
+if (print_version) {
printf ("notmuch " STRINGIFY(NOTMUCH_VERSION) "\n");
return 0;
 }
@@ -274,11 +288,11 @@ main (int argc, char *argv[])
 for (i = 0; i < ARRAY_SIZE (commands); i++) {
command = [i];

-   if (strcmp (argv[1], command->name) == 0) {
+   if (strcmp (argv[opt_index], command->name) == 0) {
int ret;
char *talloc_report;

-   ret = (command->function)(local, argc - 1, [1]);
+   ret = (command->function)(local, argc - opt_index, argv + 
opt_index);

/* in the future support for this environment variable may
 * be supplemented or replaced by command line arguments
-- 
1.7.10.4



[PATCH 2/7] CLI: remove alias machinery, and "part", "search-tags" commands

2013-01-19 Thread da...@tethera.net
From: David Bremner 

The commands are long deprecated, so removal is probably overdue. The
real motivation is to simplify argument handling for notmuch so that
we can migrate to the common argument parsing framework.
---
 NEWS   |8 
 devel/TODO |7 ---
 notmuch.c  |   50 +-
 3 files changed, 9 insertions(+), 56 deletions(-)

diff --git a/NEWS b/NEWS
index 1cb52dd..2ed472e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+Notmuch 0.16 (2013-MM-DD)
+=
+
+Command-Line Interface
+--
+
+Deprecated commands "part" and "search-tags" are removed.
+
 Notmuch 0.15 (2013-01-18)
 =

diff --git a/devel/TODO b/devel/TODO
index eb757af..3741f0e 100644
--- a/devel/TODO
+++ b/devel/TODO
@@ -118,13 +118,6 @@ file.
 Allow configuration for filename patterns that should be ignored when
 indexing.

-Replace the "notmuch part --part=id" command with "notmuch show
---part=id", (David Edmondson wants to rewrite some of "notmuch show" to
-provide more MIME-structure information in its output first).
-
-Replace the "notmuch search-tags" command with "notmuch search
---output=tags".
-
 Fix to avoid this ugly message:

(process:17197): gmime-CRITICAL **: g_mime_message_get_mime_part: 
assertion `GMIME_IS_MESSAGE (message)' failed
diff --git a/notmuch.c b/notmuch.c
index 4fc0973..f13fd27 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -31,18 +31,6 @@ typedef struct command {
 const char *summary;
 } command_t;

-#define MAX_ALIAS_SUBSTITUTIONS 3
-
-typedef struct alias {
-const char *name;
-const char *substitutions[MAX_ALIAS_SUBSTITUTIONS];
-} alias_t;
-
-alias_t aliases[] = {
-{ "part", { "show", "--format=raw"}},
-{ "search-tags", {"search", "--output=tags", "*"}}
-};
-
 static int
 notmuch_help_command (void *ctx, int argc, char *argv[]);

@@ -260,9 +248,7 @@ main (int argc, char *argv[])
 {
 void *local;
 command_t *command;
-alias_t *alias;
-unsigned int i, j;
-const char **argv_local;
+unsigned int i;

 talloc_enable_null_tracking ();

@@ -285,40 +271,6 @@ main (int argc, char *argv[])
return 0;
 }

-for (i = 0; i < ARRAY_SIZE (aliases); i++) {
-   alias = [i];
-
-   if (strcmp (argv[1], alias->name) == 0)
-   {
-   int substitutions;
-
-   argv_local = talloc_size (local, sizeof (char *) *
- (argc + MAX_ALIAS_SUBSTITUTIONS - 1));
-   if (argv_local == NULL) {
-   fprintf (stderr, "Out of memory.\n");
-   return 1;
-   }
-
-   /* Copy all substution arguments from the alias. */
-   argv_local[0] = argv[0];
-   for (j = 0; j < MAX_ALIAS_SUBSTITUTIONS; j++) {
-   if (alias->substitutions[j] == NULL)
-   break;
-   argv_local[j+1] = alias->substitutions[j];
-   }
-   substitutions = j;
-
-   /* And copy all original arguments (skipping the argument
-* that matched the alias of course. */
-   for (j = 2; j < (unsigned) argc; j++) {
-   argv_local[substitutions+j-1] = argv[j];
-   }
-
-   argc += substitutions - 1;
-   argv = (char **) argv_local;
-   }
-}
-
 for (i = 0; i < ARRAY_SIZE (commands); i++) {
command = [i];

-- 
1.7.10.4



[PATCH 1/7] emacs: don't use deprecated "notmuch search-tags" command

2013-01-19 Thread da...@tethera.net
From: David Bremner 

A followup patch will finally remove this command, so we need to stop
using it.
---
 emacs/notmuch-hello.el |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/emacs/notmuch-hello.el b/emacs/notmuch-hello.el
index 6db62a0..00b78e1 100644
--- a/emacs/notmuch-hello.el
+++ b/emacs/notmuch-hello.el
@@ -504,7 +504,7 @@ Complete list of currently available key bindings:
  (notmuch-remove-if-not
   (lambda (tag)
 (not (member tag hide-tags)))
-  (process-lines notmuch-command "search-tags"
+  (process-lines notmuch-command "search" "--output=tags" "*"

 (defun notmuch-hello-insert-header ()
   "Insert the default notmuch-hello header."
-- 
1.7.10.4



update top level argument handling

2013-01-19 Thread da...@tethera.net
The only new feature here is an option --leak-report
to notmuch new, as requested in id:m2hangivfu.fsf at guru.guru-group.fi

There is also a bunch of cleanup of the argument handling. One
casualty of this is that the use of aliases (in particular "notmuch
part" and "notmuch search-tags" is no longer supported).



the future of notmuch-vim?

2013-01-19 Thread David Bremner

So now that we've (finally) released, we can turn our minds back to
being distruptive.

I'm not sure what, if anything to do about the vim frontend.

Looking at 

http://qa.debian.org/popcon.php?package=notmuch

There is apparently still some people that use it (although notice the
"Vote" column is 0).

On the other hand

- The vim frontend is afaik the last thing depending on the legacy text
  output format.

- The plugin seems to be only semi-functional at the moment; in a quick
  test I found a message that didn't display it's content, and one that
  displayed the content, along with "junk" from the internal
  representation.

- There are now several alternatives for people whose only motivation to
  use the vim frontend was dislike of emacs (alot and notmuch-mutt).

There are several alternative vim frontends floating around in (at
least) ruby and python. I don't if they are better or worse
functionality wise. 

I'm considering stopping building debian packages for notmuch-vim, since
I don't see any current prospects for the package improving.  I'm not
sure what the equivalent thing to do upstream would be, perhaps moving
it to contrib. Or, deprecating it and then removing it.

What do people think?

d


-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 315 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20130119/c223fe34/attachment.pgp>


[PATCH] notmuch-tag: initialize with enum instead of 0.

2013-01-19 Thread da...@tethera.net
From: David Bremner 

This is just a cosmetic fix to make the "type" of ret more clear.
---
 notmuch-tag.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/notmuch-tag.c b/notmuch-tag.c
index b54c55d..d9daf8f 100644
--- a/notmuch-tag.c
+++ b/notmuch-tag.c
@@ -97,7 +97,7 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const char 
*query_string,
 notmuch_query_t *query;
 notmuch_messages_t *messages;
 notmuch_message_t *message;
-int ret = 0;
+int ret = NOTMUCH_STATUS_SUCCESS;

 /* Optimize the query so it excludes messages that already have
  * the specified set of tags. */
-- 
1.7.10.4



[PATCH] NEWS: document that print message prints all parts including hidden parts

2013-01-19 Thread David Bremner
Mark Walters  writes:

> ---
> The new invisibility code means that notmuch-show-print-message prints
> all parts of the message regardless of whether they are shown or
> hidden. This is probably a bug but the correct fix, and even the
> `correct' behaviour is not clear. So for the moment just document the
> current behaviour.

Pushed as part of the release. 

I think that one line commit messages are probably defensible when the
only change is adding NEWS.

d


[PATCH] NEWS: describe 'batch-tag' dump/restore/tag

2013-01-19 Thread David Bremner
david at tethera.net writes:

> From: David Bremner 
>
> Hopefully it is clear that more details are available in the man
> pages.

pushed as part of the release.

Mark mentioned that some motivation for batch tagging might be good; I
don't know if it's just freeze fatigue, but I'd rather add that to the
man pages later (or maybe the wiki)

d


notmuch release 0.15 now available

2013-01-19 Thread David Bremner
ion fails an error
  is thrown for the bodypart insertion function to deal with.

Disabled coding conversions when reading in `with-current-notmuch-show-message`

  Depending on the user's locale, saving attachments containing 8-bit
  data may have performed an unintentional encoding conversion,
  corrupting the saved attachment.  This has been fixed by making
  `with-current-notmuch-show-message` disable coding conversion.

Fixed errors with HTML email containing images in Emacs 24

  Emacs 24 ships with a new HTML renderer that produces better output,
  but is slightly buggy.  We work around a bug that caused it to fail
  for HTML email containing images.

Fixed handling of tags with unusual characters in them

  Emacs now handles tags containing spaces, quotes, and parenthesis.

Fixed buttonization of id: links without quote characters

  Emacs now correctly buttonizes id: links where the message ID is not
  quoted.

`notmuch-hello` refresh point placement improvements

  Refreshing the `notmuch-hello` buffer does a better job of keeping
  the point where it was.

Automatic tag changes are now unified and customizable

  All the automatic tag changes that the Emacs interface makes when
  reading, archiving, or replying to messages, can now be
  customized. Any number of tag additions and removals is supported
  through the `notmuch-show-mark-read`, `notmuch-archive-tags`, and
  `notmuch-message-replied-tags` customization variables.

Support for stashing the thread id in show view

  Invoking `notmuch-show-stash-message-id` with a prefix argument
  stashes the (local and database specific) thread id of the current
  thread instead of the message id.

New add-on tool: notmuch-pick
-

The new contrib/ tool `notmuch-pick` is an experimental threaded message
view for the emacs interface. Each message is one line in the results
and the thread structure is shown using UTF-8 box drawing characters
(similar to Mutt's threaded view). It comes between search and show in
terms of amount of output and can be useful for viewing both single
threads and multiple threads. See the notmuch-pick README file for
further details and installation.

Portability
---

notmuch now builds on OpenBSD.

Internal test framework changes
---

The emacsclient binary is now user-configurable

  The test framework now accepts TEST_EMACSCLIENT in addition to
  TEST_EMACS for configuring the emacsclient to use.  This is
  necessary to avoid using an old emacsclient with a new emacs, which
  can result in buggy behavior.

What is notmuch
===
Notmuch is a system for indexing, searching, reading, and tagging
large collections of email messages in maildir or mh format. It uses
the Xapian library to provide fast, full-text search with a convenient
search syntax.

For more about notmuch, see http://notmuchmail.org

-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 315 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20130119/c1ed7cee/attachment.pgp>


[PATCH 1/1] devel/release-checks.sh: version string problem does not halt execution

2013-01-19 Thread Tomi Ollila
Version string has strict format requirements in release-check.sh:
only numbers and periods (in sane order) are accepted.
Mismatch there used to halt further execution.
In this case, checking versions like '*~rc1' for (more) problems
was not possible.
This 'fatal error' is now changed buffered error message like in
following tests, and is displayed at the end of execution.
---
 devel/release-checks.sh | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/devel/release-checks.sh b/devel/release-checks.sh
index e1d19f2..d2bbc6a 100755
--- a/devel/release-checks.sh
+++ b/devel/release-checks.sh
@@ -53,12 +53,13 @@ fi < ./version

 readonly VERSION

+# In the rest of this file, tests collect list of errors to be fixed
+
 verfail ()
 {
echo No.
-   echo "$@"
-   echo "Please follow the instructions in RELEASING to choose a version"
-   exit 1
+   append_emsg "$@"
+   append_emsg "  Please follow the instructions in RELEASING to choose a 
version"
 }

 echo -n "Checking that '$VERSION' is good with digits and periods... "
@@ -73,8 +74,6 @@ case $VERSION in
 esac


-# In the rest of this file, tests collect list of errors to be fixed
-
 echo -n "Checking that this is Debian package for notmuch... "
 read deb_notmuch deb_version rest < debian/changelog
 if [ "$deb_notmuch" = 'notmuch' ]
-- 
1.8.0.2



notmuch release 0.15 now available

2013-01-19 Thread David Bremner

Where to obtain notmuch 0.15
===
  http://notmuchmail.org/releases/notmuch-0.15.tar.gz

Which can be verified with:

  http://notmuchmail.org/releases/notmuch-0.15.tar.gz.sha1
  7b604ec0ed56f798d1bb3ddbeeacc34a58843725  notmuch-0.15.tar.gz

  http://notmuchmail.org/releases/notmuch-0.15.tar.gz.sha1.asc
  (signed by David Bremner)

What's new in notmuch 0.15
=

General
---

Date range search support

  The `date:` prefix can now be used in queries to restrict the results
  to only messages within a particular time range (based on the Date:
  header) with a range syntax of `date:since..until`. Notmuch
  supports a wide variety of expressions in `since` and
  `until`. Please refer to the `notmuch-search-terms(7)` manual page
  for details.

Empty tag names and tags beginning with - are deprecated

  Such tags have been a frequent source of confusion and cause
  (sometimes unresolvable) conflicts with other syntax.  notmuch tag
  no longer allows such tags to be added to messages.  Removing such
  tags continues to be supported to allow cleanup of existing tags,
  but may be removed in a future release.

Command-Line Interface
--

`notmuch new` no longer chokes on mboxes

  `notmuch new` now rejects mbox files containing more than one
  message, rather than treating the file as one giant message.

Support for single message mboxes is deprecated

  For historical reasons, `notmuch new` will index mbox files
  containing a single message; however, this behavior is now
  officially deprecated.

Fixed `notmuch new` to skip ignored broken symlinks

  `notmuch new` now correctly skips symlinks if they are in the
  ignored files list.  Previously, it would abort when encountering
  broken symlink, even if it was ignored.

New dump/restore format and tagging interface

  There is a new `batch-tag` format for dump and restore that is more
  robust, particularly with respect to tags and message-ids containing
  whitespace.

  `notmuch tag` now supports the ability to read tag operations and
  queries from an input stream, in a format compatible with the new
  dump/restore format.

Bcc and Reply-To headers are now available in notmuch show json output

  The `notmuch show --format=json` now includes Bcc and Reply-To headers.
  For example notmuch Emacs client can now have these headers visible
  when the headers are added to the `notmuch-message-headers` variable.

CLI callers can now request a specific output format version

  `notmuch` subcommands that support structured output now support a
  `--format-version` argument for requesting a specific version of the
  structured output, enabling better compatibility and error handling.

`notmuch search` has gained a null character separated text output format

  The new --format=text0 output format for `notmuch search` prints
  output separated by null characters rather than newline
  characters. This is similar to the find(1) -print0 option, and works
  together with the xargs(1) -0 option.

Emacs Interface
---

Removal of the deprecated `notmuch-folders` variable

  `notmuch-folders` has been deprecated since the introduction of saved
  searches and the notmuch hello view in notmuch 0.3. `notmuch-folders`
  has now been removed. Any remaining users should migrate to
  `notmuch-saved-searches`.

Visibility of MIME parts can be toggled

  Each part of a multi-part MIME email can now be shown or hidden
  using the button at the top of each part (by pressing RET on it or
  by clicking).  For emails with multiple alternative formats (e.g.,
  plain text and HTML), only the preferred format is shown initially,
  but other formats can be shown using their part buttons.  To control
  the behavior of this, see
  `notmuch-multipart/alternative-discouraged` and
  `notmuch-show-all-multipart/alternative-parts`.

  Note notmuch-show-print-message (bound to '#' by default) will print
  all parts of multipart/alternative message regardless of whether
  they are currently hidden or shown in the buffer.

Emacs now buttonizes mid: links

  mid: links are a standardized way to link to messages by message ID
  (see RFC 2392).  Emacs now hyperlinks mid: links to the appropriate
  notmuch search.

Handle errors from bodypart insertions

  If displaying the text of a message in show mode causes an error (in
  the `notmuch-show-insert-part-*` functions), notmuch no longer cuts
  off thread display at the offending message.  The error is now
  simply displayed in place of the message.

Emacs now detects version mismatches with the notmuch CLI

  Emacs now detects and reports when the Emacs interface version and
  the notmuch CLI version are incompatible.

Improved text/calendar content handling

  Carriage returns in embedded text/calendar content caused insertion
  of the calendar content fail. Now CRs are removed before calling icalendar
  to extract icalendar data. In case icalendar extraction fails an error
  

Re: [PATCH] NEWS: describe 'batch-tag' dump/restore/tag

2013-01-19 Thread David Bremner
da...@tethera.net writes:

 From: David Bremner brem...@debian.org

 Hopefully it is clear that more details are available in the man
 pages.

pushed as part of the release.

Mark mentioned that some motivation for batch tagging might be good; I
don't know if it's just freeze fatigue, but I'd rather add that to the
man pages later (or maybe the wiki)

d
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH] NEWS: document that print message prints all parts including hidden parts

2013-01-19 Thread David Bremner
Mark Walters markwalters1...@gmail.com writes:

 ---
 The new invisibility code means that notmuch-show-print-message prints
 all parts of the message regardless of whether they are shown or
 hidden. This is probably a bug but the correct fix, and even the
 `correct' behaviour is not clear. So for the moment just document the
 current behaviour.

Pushed as part of the release. 

I think that one line commit messages are probably defensible when the
only change is adding NEWS.

d
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH] notmuch-tag: initialize with enum instead of 0.

2013-01-19 Thread david
From: David Bremner brem...@debian.org

This is just a cosmetic fix to make the type of ret more clear.
---
 notmuch-tag.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/notmuch-tag.c b/notmuch-tag.c
index b54c55d..d9daf8f 100644
--- a/notmuch-tag.c
+++ b/notmuch-tag.c
@@ -97,7 +97,7 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const char 
*query_string,
 notmuch_query_t *query;
 notmuch_messages_t *messages;
 notmuch_message_t *message;
-int ret = 0;
+int ret = NOTMUCH_STATUS_SUCCESS;
 
 /* Optimize the query so it excludes messages that already have
  * the specified set of tags. */
-- 
1.7.10.4

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


the future of notmuch-vim?

2013-01-19 Thread David Bremner

So now that we've (finally) released, we can turn our minds back to
being distruptive.

I'm not sure what, if anything to do about the vim frontend.

Looking at 

http://qa.debian.org/popcon.php?package=notmuch

There is apparently still some people that use it (although notice the
Vote column is 0).

On the other hand

- The vim frontend is afaik the last thing depending on the legacy text
  output format.

- The plugin seems to be only semi-functional at the moment; in a quick
  test I found a message that didn't display it's content, and one that
  displayed the content, along with junk from the internal
  representation.

- There are now several alternatives for people whose only motivation to
  use the vim frontend was dislike of emacs (alot and notmuch-mutt).

There are several alternative vim frontends floating around in (at
least) ruby and python. I don't if they are better or worse
functionality wise. 

I'm considering stopping building debian packages for notmuch-vim, since
I don't see any current prospects for the package improving.  I'm not
sure what the equivalent thing to do upstream would be, perhaps moving
it to contrib. Or, deprecating it and then removing it.

What do people think?

d




pgpPE6QsOjjMR.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH] notmuch-tag: initialize with enum instead of 0.

2013-01-19 Thread Tomi Ollila
On Sat, Jan 19 2013, da...@tethera.net wrote:

 From: David Bremner brem...@debian.org

 This is just a cosmetic fix to make the type of ret more clear.
 ---
  notmuch-tag.c |2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/notmuch-tag.c b/notmuch-tag.c
 index b54c55d..d9daf8f 100644
 --- a/notmuch-tag.c
 +++ b/notmuch-tag.c
 @@ -97,7 +97,7 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const 
 char *query_string,
  notmuch_query_t *query;
  notmuch_messages_t *messages;
  notmuch_message_t *message;
 -int ret = 0;
 +int ret = NOTMUCH_STATUS_SUCCESS;

LGTM.

Tomi
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 2/7] CLI: remove alias machinery, and part, search-tags commands

2013-01-19 Thread david
From: David Bremner brem...@debian.org

The commands are long deprecated, so removal is probably overdue. The
real motivation is to simplify argument handling for notmuch so that
we can migrate to the common argument parsing framework.
---
 NEWS   |8 
 devel/TODO |7 ---
 notmuch.c  |   50 +-
 3 files changed, 9 insertions(+), 56 deletions(-)

diff --git a/NEWS b/NEWS
index 1cb52dd..2ed472e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+Notmuch 0.16 (2013-MM-DD)
+=
+
+Command-Line Interface
+--
+
+Deprecated commands part and search-tags are removed.
+
 Notmuch 0.15 (2013-01-18)
 =
 
diff --git a/devel/TODO b/devel/TODO
index eb757af..3741f0e 100644
--- a/devel/TODO
+++ b/devel/TODO
@@ -118,13 +118,6 @@ file.
 Allow configuration for filename patterns that should be ignored when
 indexing.
 
-Replace the notmuch part --part=id command with notmuch show
---part=id, (David Edmondson wants to rewrite some of notmuch show to
-provide more MIME-structure information in its output first).
-
-Replace the notmuch search-tags command with notmuch search
---output=tags.
-
 Fix to avoid this ugly message:
 
(process:17197): gmime-CRITICAL **: g_mime_message_get_mime_part: 
assertion `GMIME_IS_MESSAGE (message)' failed
diff --git a/notmuch.c b/notmuch.c
index 4fc0973..f13fd27 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -31,18 +31,6 @@ typedef struct command {
 const char *summary;
 } command_t;
 
-#define MAX_ALIAS_SUBSTITUTIONS 3
-
-typedef struct alias {
-const char *name;
-const char *substitutions[MAX_ALIAS_SUBSTITUTIONS];
-} alias_t;
-
-alias_t aliases[] = {
-{ part, { show, --format=raw}},
-{ search-tags, {search, --output=tags, *}}
-};
-
 static int
 notmuch_help_command (void *ctx, int argc, char *argv[]);
 
@@ -260,9 +248,7 @@ main (int argc, char *argv[])
 {
 void *local;
 command_t *command;
-alias_t *alias;
-unsigned int i, j;
-const char **argv_local;
+unsigned int i;
 
 talloc_enable_null_tracking ();
 
@@ -285,40 +271,6 @@ main (int argc, char *argv[])
return 0;
 }
 
-for (i = 0; i  ARRAY_SIZE (aliases); i++) {
-   alias = aliases[i];
-
-   if (strcmp (argv[1], alias-name) == 0)
-   {
-   int substitutions;
-
-   argv_local = talloc_size (local, sizeof (char *) *
- (argc + MAX_ALIAS_SUBSTITUTIONS - 1));
-   if (argv_local == NULL) {
-   fprintf (stderr, Out of memory.\n);
-   return 1;
-   }
-
-   /* Copy all substution arguments from the alias. */
-   argv_local[0] = argv[0];
-   for (j = 0; j  MAX_ALIAS_SUBSTITUTIONS; j++) {
-   if (alias-substitutions[j] == NULL)
-   break;
-   argv_local[j+1] = alias-substitutions[j];
-   }
-   substitutions = j;
-
-   /* And copy all original arguments (skipping the argument
-* that matched the alias of course. */
-   for (j = 2; j  (unsigned) argc; j++) {
-   argv_local[substitutions+j-1] = argv[j];
-   }
-
-   argc += substitutions - 1;
-   argv = (char **) argv_local;
-   }
-}
-
 for (i = 0; i  ARRAY_SIZE (commands); i++) {
command = commands[i];
 
-- 
1.7.10.4

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 6/7] man: document NOTMUCH_TALLOC_REPORT environment variable

2013-01-19 Thread david
From: David Bremner brem...@debian.org

---
 man/man1/notmuch.1 |7 +++
 1 file changed, 7 insertions(+)

diff --git a/man/man1/notmuch.1 b/man/man1/notmuch.1
index 5c58c41..391eb88 100644
--- a/man/man1/notmuch.1
+++ b/man/man1/notmuch.1
@@ -155,6 +155,13 @@ behavior of notmuch.
 .B NOTMUCH_CONFIG
 Specifies the location of the notmuch configuration file. Notmuch will
 use ${HOME}/.notmuch\-config if this variable is not set.
+
+.TP
+.B NOTMUCH_TALLOC_REPORT
+Location to write a talloc memory usage report. Overridden by the
+.B --leak-report
+option.
+
 .SH SEE ALSO
 
 \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1),
-- 
1.7.10.4

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


update top level argument handling

2013-01-19 Thread david
The only new feature here is an option --leak-report
to notmuch new, as requested in id:m2hangivfu@guru.guru-group.fi

There is also a bunch of cleanup of the argument handling. One
casualty of this is that the use of aliases (in particular notmuch
part and notmuch search-tags is no longer supported).

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 7/7] CLI: add simple error handling for talloc logging

2013-01-19 Thread david
From: David Bremner brem...@debian.org

This really should have been there before. I think it's better to do
the actual operation and then possibly fail writing the memory log,
but it would not be too hard to change it to abort earlier.
---
 notmuch.c |7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/notmuch.c b/notmuch.c
index f8d4b35..c3336e8 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -301,7 +301,12 @@ main (int argc, char *argv[])
 
if (leak_report  (strcmp (leak_report, ) != 0)) {
FILE *report = fopen (leak_report, w);
-   talloc_report_full (NULL, report);
+   if (report) {
+   talloc_report_full (NULL, report);
+   } else {
+   ret = 1;
+   perror (leak_report);
+   }
}
 
return ret;
-- 
1.7.10.4

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 5/7] CLI: add --leak-report top level option

2013-01-19 Thread david
From: David Bremner brem...@debian.org

This roughly mimics the samba4 argument. The presence of the command
line argument overrides any value of NOTMUCH_TALLOC_REPORT in the
environment.
---
 man/man1/notmuch.1 |8 
 notmuch.c  |   18 +++---
 2 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/man/man1/notmuch.1 b/man/man1/notmuch.1
index 6bf9b2e..5c58c41 100644
--- a/man/man1/notmuch.1
+++ b/man/man1/notmuch.1
@@ -70,6 +70,14 @@ Print a synopsis of available commands and exit.
 Print the installed version of notmuch, and exit.
 .RE
 
+.RS 4
+.TP 4
+.BI \-\-leak-report= path
+
+Write a detailed report of all memory allocated via talloc to
+.I path
+.RE
+
 .SH COMMANDS
 
 
diff --git a/notmuch.c b/notmuch.c
index a674481..f8d4b35 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -250,11 +250,13 @@ main (int argc, char *argv[])
 command_t *command;
 unsigned int i;
 notmuch_bool_t print_help=FALSE, print_version=FALSE;
+const char* leak_report=NULL;
 int opt_index;
 
 notmuch_opt_desc_t options[] = {
{ NOTMUCH_OPT_BOOLEAN, print_help, help, 'h', 0 },
{ NOTMUCH_OPT_BOOLEAN, print_version, version, 'v', 0 },
+   { NOTMUCH_OPT_STRING, leak_report, leak-report, 'l', 0 },
{ 0, 0, 0, 0, 0 }
 };
 
@@ -290,21 +292,15 @@ main (int argc, char *argv[])
 
if (strcmp (argv[opt_index], command-name) == 0) {
int ret;
-   char *talloc_report;
 
ret = (command-function)(local, argc - opt_index, argv + 
opt_index);
 
-   /* in the future support for this environment variable may
-* be supplemented or replaced by command line arguments
-* --leak-report and/or --leak-report-full */
-
-   talloc_report = getenv (NOTMUCH_TALLOC_REPORT);
-
-   /* this relies on the previous call to
-* talloc_enable_null_tracking */
+   if (leak_report == NULL) {
+   leak_report = getenv (NOTMUCH_TALLOC_REPORT);
+   }
 
-   if (talloc_report  strcmp (talloc_report, ) != 0) {
-   FILE *report = fopen (talloc_report, w);
+   if (leak_report  (strcmp (leak_report, ) != 0)) {
+   FILE *report = fopen (leak_report, w);
talloc_report_full (NULL, report);
}
 
-- 
1.7.10.4

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 3/7] CLI: convert top level argument parsing to use command-line-arguments

2013-01-19 Thread david
From: David Bremner brem...@debian.org

This isn't really a win for conciseness yet, but will make it easier
to add options.
---
 notmuch.c |   22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/notmuch.c b/notmuch.c
index f13fd27..a674481 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -249,6 +249,14 @@ main (int argc, char *argv[])
 void *local;
 command_t *command;
 unsigned int i;
+notmuch_bool_t print_help=FALSE, print_version=FALSE;
+int opt_index;
+
+notmuch_opt_desc_t options[] = {
+   { NOTMUCH_OPT_BOOLEAN, print_help, help, 'h', 0 },
+   { NOTMUCH_OPT_BOOLEAN, print_version, version, 'v', 0 },
+   { 0, 0, 0, 0, 0 }
+};
 
 talloc_enable_null_tracking ();
 
@@ -263,10 +271,16 @@ main (int argc, char *argv[])
 if (argc == 1)
return notmuch (local);
 
-if (strcmp (argv[1], --help) == 0)
+opt_index = parse_arguments (argc, argv, options, 1);
+if (opt_index  0) {
+   /* diagnostics already printed */
+   return 1;
+}
+
+if (print_help)
return notmuch_help_command (NULL, argc - 1, argv[1]);
 
-if (strcmp (argv[1], --version) == 0) {
+if (print_version) {
printf (notmuch  STRINGIFY(NOTMUCH_VERSION) \n);
return 0;
 }
@@ -274,11 +288,11 @@ main (int argc, char *argv[])
 for (i = 0; i  ARRAY_SIZE (commands); i++) {
command = commands[i];
 
-   if (strcmp (argv[1], command-name) == 0) {
+   if (strcmp (argv[opt_index], command-name) == 0) {
int ret;
char *talloc_report;
 
-   ret = (command-function)(local, argc - 1, argv[1]);
+   ret = (command-function)(local, argc - opt_index, argv + 
opt_index);
 
/* in the future support for this environment variable may
 * be supplemented or replaced by command line arguments
-- 
1.7.10.4

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH 4/7] man: document existing top level options

2013-01-19 Thread david
From: David Bremner brem...@debian.org

The options --help and --version were not documented before.  One
could quibble about how useful that documentation is, but we will soon
add more options.
---
 man/man1/notmuch.1 |   22 +-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/man/man1/notmuch.1 b/man/man1/notmuch.1
index 69805cb..6bf9b2e 100644
--- a/man/man1/notmuch.1
+++ b/man/man1/notmuch.1
@@ -21,7 +21,7 @@
 notmuch \- thread-based email index, search, and tagging
 .SH SYNOPSIS
 .B notmuch
-.IR command  [ args  ...]
+.RI [ option  ...]  command   [ arg  ...]
 .SH DESCRIPTION
 Notmuch is a command-line based program for indexing, searching,
 reading, and tagging large collections of email messages.
@@ -50,6 +50,26 @@ interfaces to notmuch. The emacs-based interface to notmuch 
(available under
 in the Notmuch source distribution) is probably the most widely used at
 this time.
 
+.SH OPTIONS
+
+Supported global options for
+.B notmuch
+include
+
+.RS 4
+.TP 4
+.B \-\-help
+
+Print a synopsis of available commands and exit.
+.RE
+
+.RS 4
+.TP 4
+.B \-\-version
+
+Print the installed version of notmuch, and exit.
+.RE
+
 .SH COMMANDS
 
 
-- 
1.7.10.4

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH] notmuch-tag: initialize with enum instead of 0.

2013-01-19 Thread David Bremner
da...@tethera.net writes:

 From: David Bremner brem...@debian.org

 This is just a cosmetic fix to make the type of ret more clear.

Pushed. I even caught the '.' and the end of the commit subject.
No idea why that is so hard for me.

d
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 00/20] insert command

2013-01-19 Thread Peter Wang
This mainly addresses review comments from v2
and rebases on top of tag-util.c.

Peter Wang (20):
  cli: add stub for insert command
  insert: open Maildir tmp file
  insert: copy stdin to Maildir tmp file
  insert: move file from Maildir tmp to new
  insert: add new message to database
  insert: apply default tags to new message
  tag-util: do not reset list in parse_tag_command_line
  tag-util: move out 'tag' command-line checks
  insert: parse and apply command-line tag operations
  insert: support --folder option
  insert: prevent writes outside Maildir hierarchy
  insert: add --create-folder option
  insert: fsync after writing tmp file
  insert: fsync new directory after rename
  insert: fsync parent directory after mkdir
  insert: trap SIGINT and clean up
  insert: add copyright line from notmuch-deliver
  man: document 'insert' command
  man: reference notmuch-insert.1
  test: add tests for insert

 Makefile.local  |   1 +
 man/Makefile.local  |   1 +
 man/man1/notmuch-config.1   |   4 +-
 man/man1/notmuch-count.1|   4 +-
 man/man1/notmuch-dump.1 |   4 +-
 man/man1/notmuch-insert.1   |  59 +
 man/man1/notmuch-new.1  |   4 +-
 man/man1/notmuch-reply.1|   3 +-
 man/man1/notmuch-restore.1  |   3 +-
 man/man1/notmuch-search.1   |   3 +-
 man/man1/notmuch-show.1 |   3 +-
 man/man1/notmuch-tag.1  |   3 +-
 man/man1/notmuch.1  |   3 +-
 man/man5/notmuch-hooks.5|   4 +-
 man/man7/notmuch-search-terms.7 |   3 +-
 notmuch-client.h|   3 +
 notmuch-insert.c| 482 
 notmuch-tag.c   |  10 +
 notmuch.c   |   3 +
 tag-util.c  |  12 -
 tag-util.h  |   2 +
 test/insert | 106 +
 test/notmuch-test   |   1 +
 23 files changed, 692 insertions(+), 29 deletions(-)
 create mode 100644 man/man1/notmuch-insert.1
 create mode 100644 notmuch-insert.c
 create mode 100755 test/insert

-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 01/20] cli: add stub for insert command

2013-01-19 Thread Peter Wang
The notmuch insert command should read a message from standard input
and deliver it to a Maildir folder, and then incorporate the message
into the notmuch database.  Essentially it moves the functionality of
notmuch-deliver into notmuch.

Though it could be used as an alternative to notmuch new, the reason
I want this is to allow my notmuch frontend to add postponed or sent
messages to the mail store and notmuch database, without resorting to
another tool (e.g. notmuch-deliver) nor directly modifying the maildir.
---
 Makefile.local   |  1 +
 notmuch-client.h |  3 +++
 notmuch-insert.c | 43 +++
 notmuch.c|  3 +++
 4 files changed, 50 insertions(+)
 create mode 100644 notmuch-insert.c

diff --git a/Makefile.local b/Makefile.local
index c274f07..bb2381d 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -261,6 +261,7 @@ notmuch_client_srcs =   \
notmuch-config.c\
notmuch-count.c \
notmuch-dump.c  \
+   notmuch-insert.c\
notmuch-new.c   \
notmuch-reply.c \
notmuch-restore.c   \
diff --git a/notmuch-client.h b/notmuch-client.h
index 5f28836..af7d094 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -175,6 +175,9 @@ int
 notmuch_dump_command (void *ctx, int argc, char *argv[]);
 
 int
+notmuch_insert_command (void *ctx, int argc, char *argv[]);
+
+int
 notmuch_new_command (void *ctx, int argc, char *argv[]);
 
 int
diff --git a/notmuch-insert.c b/notmuch-insert.c
new file mode 100644
index 000..c1d359c
--- /dev/null
+++ b/notmuch-insert.c
@@ -0,0 +1,43 @@
+/* notmuch - Not much of an email program, (just index and search)
+ *
+ * Copyright © 2013 Peter Wang
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 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/ .
+ *
+ * Author: Peter Wang noval...@gmail.com
+ */
+
+#include notmuch-client.h
+
+int
+notmuch_insert_command (void *ctx, int argc, char *argv[])
+{
+notmuch_config_t *config;
+notmuch_database_t *notmuch;
+const char *db_path;
+
+config = notmuch_config_open (ctx, NULL, NULL);
+if (config == NULL)
+   return 1;
+
+db_path = notmuch_config_get_database_path (config);
+
+if (notmuch_database_open (notmuch_config_get_database_path (config),
+  NOTMUCH_DATABASE_MODE_READ_WRITE, notmuch))
+   return 1;
+
+notmuch_database_destroy (notmuch);
+
+return 1;
+}
diff --git a/notmuch.c b/notmuch.c
index 4fc0973..1c3b893 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -53,6 +53,9 @@ static command_t commands[] = {
 { new, notmuch_new_command,
   [options...],
   Find and import new messages to the notmuch database. },
+{ insert, notmuch_insert_command,
+  [options...] [--] [+tag|-tag ...]  message,
+  Add a new message into the maildir and notmuch database. },
 { search, notmuch_search_command,
   [options...] search-terms [...],
   Search for messages matching the given search terms. },
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 02/20] insert: open Maildir tmp file

2013-01-19 Thread Peter Wang
Open a unique file in the Maildir tmp directory.
The new message is not yet copied into the file.
---
 notmuch-insert.c | 105 ++-
 1 file changed, 104 insertions(+), 1 deletion(-)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index c1d359c..7d100ae 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -20,12 +20,107 @@
 
 #include notmuch-client.h
 
+#include sys/types.h
+#include sys/stat.h
+#include fcntl.h
+
+/* Like gethostname but guarantees that a null-terminated hostname is
+ * returned, even if it has to make one up.
+ * Returns true unless hostname contains a slash. */
+static notmuch_bool_t
+safe_gethostname (char *hostname, size_t len)
+{
+if (gethostname (hostname, len) == -1) {
+   strncpy (hostname, unknown, len);
+}
+hostname[len - 1] = '\0';
+
+return (strchr (hostname, '/') == NULL);
+}
+
+/* Open a unique file in the Maildir 'tmp' directory.
+ * Returns the file descriptor on success, or -1 on failure.
+ * On success, file paths for the message in the 'tmp' and 'new'
+ * directories are returned via tmppath and newpath. */
+static int
+maildir_open_tmp_file (void *ctx, const char *dir,
+  char **tmppath, char **newpath)
+{
+pid_t pid;
+char hostname[256];
+struct timeval tv;
+char *filename;
+int fd = -1;
+
+/* We follow the Dovecot file name generation algorithm. */
+pid = getpid ();
+if (! safe_gethostname (hostname, sizeof (hostname))) {
+   fprintf (stderr, Error: invalid host name.\n);
+   return -1;
+}
+do {
+   gettimeofday (tv, NULL);
+   filename = talloc_asprintf (ctx, %ld.M%ldP%d.%s,
+   tv.tv_sec, tv.tv_usec, pid, hostname);
+   if (! filename) {
+   fprintf (stderr, Out of memory\n);
+   return -1;
+   }
+
+   *tmppath = talloc_asprintf (ctx, %s/tmp/%s, dir, filename);
+   if (! *tmppath) {
+   fprintf (stderr, Out of memory\n);
+   return -1;
+   }
+
+   fd = open (*tmppath, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600);
+} while (fd == -1  errno == EEXIST);
+
+if (fd == -1) {
+   fprintf (stderr, Error: opening %s: %s\n, *tmppath, strerror (errno));
+   return -1;
+}
+
+*newpath = talloc_asprintf (ctx, %s/new/%s, dir, filename);
+if (! *newpath) {
+   fprintf (stderr, Out of memory\n);
+   close (fd);
+   unlink (*tmppath);
+   return -1;
+}
+
+talloc_free (filename);
+
+return fd;
+}
+
+static notmuch_bool_t
+insert_message (void *ctx, notmuch_database_t *notmuch, int fdin,
+   const char *dir)
+{
+char *tmppath;
+char *newpath;
+int fdout;
+
+fdout = maildir_open_tmp_file (ctx, dir, tmppath, newpath);
+if (fdout  0) {
+   return FALSE;
+}
+
+/* For now we just delete the tmp file immediately. */
+close (fdout);
+unlink (tmppath);
+return FALSE;
+}
+
 int
 notmuch_insert_command (void *ctx, int argc, char *argv[])
 {
 notmuch_config_t *config;
 notmuch_database_t *notmuch;
 const char *db_path;
+char *maildir;
+notmuch_bool_t ret;
 
 config = notmuch_config_open (ctx, NULL, NULL);
 if (config == NULL)
@@ -33,11 +128,19 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
 
 db_path = notmuch_config_get_database_path (config);
 
+maildir = talloc_asprintf (ctx, %s, db_path);
+if (! maildir) {
+   fprintf (stderr, Out of memory\n);
+   return 1;
+}
+
 if (notmuch_database_open (notmuch_config_get_database_path (config),
   NOTMUCH_DATABASE_MODE_READ_WRITE, notmuch))
return 1;
 
+ret = insert_message (ctx, notmuch, STDIN_FILENO, maildir);
+
 notmuch_database_destroy (notmuch);
 
-return 1;
+return (ret) ? 0 : 1;
 }
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 03/20] insert: copy stdin to Maildir tmp file

2013-01-19 Thread Peter Wang
Read the new message from standard input into the Maildir tmp file.
---
 notmuch-insert.c | 51 +++
 1 file changed, 47 insertions(+), 4 deletions(-)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index 7d100ae..38e815f 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -94,6 +94,47 @@ maildir_open_tmp_file (void *ctx, const char *dir,
 return fd;
 }
 
+/* Copy the contents of standard input (fdin) into fdout. */
+static notmuch_bool_t
+copy_stdin (int fdin, int fdout)
+{
+char buf[4096];
+char *p;
+ssize_t remain;
+ssize_t written;
+
+for (;;) {
+   remain = read (fdin, buf, sizeof (buf));
+   if (remain == 0)
+   break;
+   if (remain  0) {
+   if (errno == EINTR)
+   continue;
+   fprintf (stderr, Error: reading from standard input: %s\n,
+strerror (errno));
+   return FALSE;
+   }
+
+   p = buf;
+   do {
+   written = write (fdout, p, remain);
+   if (written == 0)
+   return FALSE;
+   if (written  0) {
+   if (errno == EINTR)
+   continue;
+   fprintf (stderr, Error: writing to temporary file: %s,
+strerror (errno));
+   return FALSE;
+   }
+   p += written;
+   remain -= written;
+   } while (remain  0);
+}
+
+return TRUE;
+}
+
 static notmuch_bool_t
 insert_message (void *ctx, notmuch_database_t *notmuch, int fdin,
const char *dir)
@@ -101,16 +142,18 @@ insert_message (void *ctx, notmuch_database_t *notmuch, 
int fdin,
 char *tmppath;
 char *newpath;
 int fdout;
+notmuch_bool_t ret;
 
 fdout = maildir_open_tmp_file (ctx, dir, tmppath, newpath);
 if (fdout  0) {
return FALSE;
 }
-
-/* For now we just delete the tmp file immediately. */
+ret = copy_stdin (fdin, fdout);
 close (fdout);
-unlink (tmppath);
-return FALSE;
+if (!ret) {
+   unlink (tmppath);
+}
+return ret;
 }
 
 int
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 04/20] insert: move file from Maildir tmp to new

2013-01-19 Thread Peter Wang
Atomically move the new message file from the Maildir 'tmp' directory
to 'new'.
---
 notmuch-insert.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index 38e815f..c0289d9 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -94,6 +94,24 @@ maildir_open_tmp_file (void *ctx, const char *dir,
 return fd;
 }
 
+/* Atomically move the new message file from the Maildir 'tmp' directory
+ * to the 'new' directory.
+ *
+ * We follow the Dovecot recommendation to simply use rename()
+ * instead of link() and unlink().  See also:
+ * http://wiki.dovecot.org/MailboxFormat/Maildir#Mail_delivery
+ */
+static notmuch_bool_t
+maildir_move_tmp_to_new (const char *tmppath, const char *newpath)
+{
+if (rename (tmppath, newpath) != 0) {
+   fprintf (stderr, Error: rename() failed: %s\n, strerror (errno));
+   return FALSE;
+}
+
+return TRUE;
+}
+
 /* Copy the contents of standard input (fdin) into fdout. */
 static notmuch_bool_t
 copy_stdin (int fdin, int fdout)
@@ -150,6 +168,9 @@ insert_message (void *ctx, notmuch_database_t *notmuch, int 
fdin,
 }
 ret = copy_stdin (fdin, fdout);
 close (fdout);
+if (ret) {
+   ret = maildir_move_tmp_to_new (tmppath, newpath);
+}
 if (!ret) {
unlink (tmppath);
 }
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 05/20] insert: add new message to database

2013-01-19 Thread Peter Wang
Add the new message to the notmuch database, renaming the file to encode
notmuch tags as maildir flags.
---
 notmuch-insert.c | 49 -
 1 file changed, 48 insertions(+), 1 deletion(-)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index c0289d9..498421d 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -153,6 +153,44 @@ copy_stdin (int fdin, int fdout)
 return TRUE;
 }
 
+/* Add the specified message file to the notmuch database.
+ * The file is renamed to encode notmuch tags as maildir flags. */
+static notmuch_bool_t
+add_file_to_database (notmuch_database_t *notmuch, const char *path)
+{
+notmuch_message_t *message;
+notmuch_status_t status;
+
+status = notmuch_database_add_message (notmuch, path, message);
+switch (status) {
+case NOTMUCH_STATUS_SUCCESS:
+   break;
+case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID:
+   fprintf (stderr, Warning: duplicate message.\n);
+   break;
+default:
+case NOTMUCH_STATUS_FILE_NOT_EMAIL:
+case NOTMUCH_STATUS_READ_ONLY_DATABASE:
+case NOTMUCH_STATUS_XAPIAN_EXCEPTION:
+case NOTMUCH_STATUS_OUT_OF_MEMORY:
+case NOTMUCH_STATUS_FILE_ERROR:
+case NOTMUCH_STATUS_NULL_POINTER:
+case NOTMUCH_STATUS_TAG_TOO_LONG:
+case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW:
+case NOTMUCH_STATUS_UNBALANCED_ATOMIC:
+case NOTMUCH_STATUS_LAST_STATUS:
+   fprintf (stderr, Error: failed to add `%s' to notmuch database: %s\n,
+path, notmuch_status_to_string (status));
+   return FALSE;
+}
+
+notmuch_message_tags_to_maildir_flags (message);
+
+notmuch_message_destroy (message);
+
+return TRUE;
+}
+
 static notmuch_bool_t
 insert_message (void *ctx, notmuch_database_t *notmuch, int fdin,
const char *dir)
@@ -173,8 +211,17 @@ insert_message (void *ctx, notmuch_database_t *notmuch, 
int fdin,
 }
 if (!ret) {
unlink (tmppath);
+   return FALSE;
 }
-return ret;
+
+ret = add_file_to_database (notmuch, newpath);
+if (!ret) {
+   /* XXX maybe there should be an option to keep the file in maildir? */
+   unlink (newpath);
+   return FALSE;
+}
+
+return TRUE;
 }
 
 int
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 06/20] insert: apply default tags to new message

2013-01-19 Thread Peter Wang
Apply the new.tags to messages added by 'insert'.  This mirrors the
behaviour if the message were delivered by a separate tool followed by
'notmuch new'.
---
 notmuch-insert.c | 29 +++--
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index 498421d..8388d07 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -19,6 +19,7 @@
  */
 
 #include notmuch-client.h
+#include tag-util.h
 
 #include sys/types.h
 #include sys/stat.h
@@ -153,10 +154,11 @@ copy_stdin (int fdin, int fdout)
 return TRUE;
 }
 
-/* Add the specified message file to the notmuch database.
+/* Add the specified message file to the notmuch database, applying tags.
  * The file is renamed to encode notmuch tags as maildir flags. */
 static notmuch_bool_t
-add_file_to_database (notmuch_database_t *notmuch, const char *path)
+add_file_to_database (notmuch_database_t *notmuch, const char *path,
+ tag_op_list_t *tag_ops)
 {
 notmuch_message_t *message;
 notmuch_status_t status;
@@ -184,7 +186,7 @@ add_file_to_database (notmuch_database_t *notmuch, const 
char *path)
return FALSE;
 }
 
-notmuch_message_tags_to_maildir_flags (message);
+tag_op_list_apply (message, tag_ops, TAG_FLAG_MAILDIR_SYNC);
 
 notmuch_message_destroy (message);
 
@@ -193,7 +195,7 @@ add_file_to_database (notmuch_database_t *notmuch, const 
char *path)
 
 static notmuch_bool_t
 insert_message (void *ctx, notmuch_database_t *notmuch, int fdin,
-   const char *dir)
+   const char *dir, tag_op_list_t *tag_ops)
 {
 char *tmppath;
 char *newpath;
@@ -214,7 +216,7 @@ insert_message (void *ctx, notmuch_database_t *notmuch, int 
fdin,
return FALSE;
 }
 
-ret = add_file_to_database (notmuch, newpath);
+ret = add_file_to_database (notmuch, newpath, tag_ops);
 if (!ret) {
/* XXX maybe there should be an option to keep the file in maildir? */
unlink (newpath);
@@ -230,7 +232,11 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
 notmuch_config_t *config;
 notmuch_database_t *notmuch;
 const char *db_path;
+const char **new_tags;
+size_t new_tags_length;
+tag_op_list_t *tag_ops;
 char *maildir;
+unsigned int i;
 notmuch_bool_t ret;
 
 config = notmuch_config_open (ctx, NULL, NULL);
@@ -238,6 +244,17 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
return 1;
 
 db_path = notmuch_config_get_database_path (config);
+new_tags = notmuch_config_get_new_tags (config, new_tags_length);
+
+tag_ops = tag_op_list_create (ctx);
+if (tag_ops == NULL) {
+   fprintf (stderr, Out of memory.\n);
+   return 1;
+}
+for (i = 0; i  new_tags_length; i++) {
+   if (tag_op_list_append (tag_ops, new_tags[i], FALSE))
+   return 1;
+}
 
 maildir = talloc_asprintf (ctx, %s, db_path);
 if (! maildir) {
@@ -249,7 +266,7 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
   NOTMUCH_DATABASE_MODE_READ_WRITE, notmuch))
return 1;
 
-ret = insert_message (ctx, notmuch, STDIN_FILENO, maildir);
+ret = insert_message (ctx, notmuch, STDIN_FILENO, maildir, tag_ops);
 
 notmuch_database_destroy (notmuch);
 
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 07/20] tag-util: do not reset list in parse_tag_command_line

2013-01-19 Thread Peter Wang
No current callers of parse_tag_command_line require that it clear its
tag list argument.  The notmuch 'insert' command will be better served
if the function modifies a pre-populated list (of new.tags) instead of
clobbering it outright.
---
 tag-util.c | 2 --
 tag-util.h | 2 ++
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tag-util.c b/tag-util.c
index 701d329..3f9da05 100644
--- a/tag-util.c
+++ b/tag-util.c
@@ -165,8 +165,6 @@ parse_tag_command_line (void *ctx, int argc, char **argv,
 
 int i;
 
-tag_op_list_reset (tag_ops);
-
 for (i = 0; i  argc; i++) {
if (strcmp (argv[i], --) == 0) {
i++;
diff --git a/tag-util.h b/tag-util.h
index 246de85..4628f16 100644
--- a/tag-util.h
+++ b/tag-util.h
@@ -81,6 +81,8 @@ parse_tag_line (void *ctx, char *line,
  * Output Parameters:
  * ops contains a list of tag operations
  * query_str the search terms.
+ *
+ * The ops argument is not cleared.
  */
 
 tag_parse_status_t
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 08/20] tag-util: move out 'tag' command-line checks

2013-01-19 Thread Peter Wang
parse_tag_command_line checked for two error conditions which are
specific to the 'tag' command.  It can be reused for the notmuch
'insert' command if we move the checks out, into notmuch-tag.c.
---
 notmuch-tag.c | 10 ++
 tag-util.c| 10 --
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/notmuch-tag.c b/notmuch-tag.c
index d9daf8f..a901dad 100644
--- a/notmuch-tag.c
+++ b/notmuch-tag.c
@@ -234,6 +234,16 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
if (parse_tag_command_line (ctx, argc - opt_index, argv + opt_index,
query_string, tag_ops))
return 1;
+
+   if (tag_op_list_size (tag_ops) == 0) {
+   fprintf (stderr, Error: 'notmuch tag' requires at least one tag to 
add or remove.\n);
+   return 1;
+   }
+
+   if (*query_string == '\0') {
+   fprintf (stderr, Error: notmuch tag requires at least one search 
term.\n);
+   return 1;
+   }
 }
 
 config = notmuch_config_open (ctx, NULL, NULL);
diff --git a/tag-util.c b/tag-util.c
index 3f9da05..41f2c09 100644
--- a/tag-util.c
+++ b/tag-util.c
@@ -186,18 +186,8 @@ parse_tag_command_line (void *ctx, int argc, char **argv,
tag_op_list_append (tag_ops, argv[i] + 1, is_remove);
 }
 
-if (tag_op_list_size (tag_ops) == 0) {
-   fprintf (stderr, Error: 'notmuch tag' requires at least one tag to add 
or remove.\n);
-   return TAG_PARSE_INVALID;
-}
-
 *query_str = query_string_from_args (ctx, argc - i, argv[i]);
 
-if (*query_str == NULL || **query_str == '\0') {
-   fprintf (stderr, Error: notmuch tag requires at least one search 
term.\n);
-   return TAG_PARSE_INVALID;
-}
-
 return TAG_PARSE_SUCCESS;
 }
 
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 09/20] insert: parse and apply command-line tag operations

2013-01-19 Thread Peter Wang
Parse +tag and -tag operations on the 'insert' command-line
and apply them to the inserted message in addition to new.tags.
---
 notmuch-insert.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index 8388d07..b0ac174 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -235,7 +235,9 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
 const char **new_tags;
 size_t new_tags_length;
 tag_op_list_t *tag_ops;
+char *query_string = NULL;
 char *maildir;
+int opt_index = 1;
 unsigned int i;
 notmuch_bool_t ret;
 
@@ -256,6 +258,15 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
return 1;
 }
 
+if (parse_tag_command_line (ctx, argc - opt_index, argv + opt_index,
+   query_string, tag_ops))
+   return 1;
+
+if (*query_string != '\0') {
+   fprintf (stderr, Error: unexpected query string: %s\n, query_string);
+   return 1;
+}
+
 maildir = talloc_asprintf (ctx, %s, db_path);
 if (! maildir) {
fprintf (stderr, Out of memory\n);
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 10/20] insert: support --folder option

2013-01-19 Thread Peter Wang
Allow the new message to be inserted into a folder within the Maildir
hierarchy instead of the top-level folder.
---
 notmuch-insert.c | 22 --
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index b0ac174..ba8cf5a 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -236,11 +236,25 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
 size_t new_tags_length;
 tag_op_list_t *tag_ops;
 char *query_string = NULL;
+const char *folder = NULL;
 char *maildir;
-int opt_index = 1;
+int opt_index;
 unsigned int i;
 notmuch_bool_t ret;
 
+notmuch_opt_desc_t options[] = {
+   { NOTMUCH_OPT_STRING, folder, folder, 0, 0 },
+   { NOTMUCH_OPT_END, 0, 0, 0, 0 }
+};
+
+opt_index = parse_arguments (argc, argv, options, 1);
+
+if (opt_index  0) {
+   fprintf (stderr, Error: bad argument to notmuch insert: %s\n,
+argv[-opt_index]);
+   return 1;
+}
+
 config = notmuch_config_open (ctx, NULL, NULL);
 if (config == NULL)
return 1;
@@ -267,7 +281,11 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
return 1;
 }
 
-maildir = talloc_asprintf (ctx, %s, db_path);
+if (folder != NULL) {
+   maildir = talloc_asprintf (ctx, %s/%s, db_path, folder);
+} else {
+   maildir = talloc_asprintf (ctx, %s, db_path);
+}
 if (! maildir) {
fprintf (stderr, Out of memory\n);
return 1;
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 11/20] insert: prevent writes outside Maildir hierarchy

2013-01-19 Thread Peter Wang
Don't accept a --folder name that contains a .. component,
in order to prevent writing outside of the Maildir hierarchy.
---
 notmuch-insert.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index ba8cf5a..67ef94a 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -39,6 +39,23 @@ safe_gethostname (char *hostname, size_t len)
 return (strchr (hostname, '/') == NULL);
 }
 
+/* Check the specified folder name does not contain a directory
+ * component .. to prevent writes outside of the Maildir hierarchy. */
+static notmuch_bool_t
+check_folder_name (const char *folder)
+{
+const char *p = folder;
+
+for (;;) {
+   if ((p[0] == '.')  (p[1] == '.')  (p[2] == '\0' || p[2] == '/'))
+   return FALSE;
+   p = strchr (p, '/');
+   if (!p)
+   return TRUE;
+   p++;
+}
+}
+
 /* Open a unique file in the Maildir 'tmp' directory.
  * Returns the file descriptor on success, or -1 on failure.
  * On success, file paths for the message in the 'tmp' and 'new'
@@ -282,6 +299,10 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
 }
 
 if (folder != NULL) {
+   if (! check_folder_name (folder)) {
+   fprintf (stderr, Error: bad folder name: %s\n, folder);
+   return 1;
+   }
maildir = talloc_asprintf (ctx, %s/%s, db_path, folder);
 } else {
maildir = talloc_asprintf (ctx, %s, db_path);
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 12/20] insert: add --create-folder option

2013-01-19 Thread Peter Wang
Support an option to create a new folder in the maildir.
---
 notmuch-insert.c | 88 
 1 file changed, 88 insertions(+)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index 67ef94a..85acaea 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -56,6 +56,87 @@ check_folder_name (const char *folder)
 }
 }
 
+/* Make the given directory, succeeding if it already exists. */
+static notmuch_bool_t
+make_directory (char *path, int mode)
+{
+if (mkdir (path, mode) != 0)
+   return (errno == EEXIST);
+return TRUE;
+}
+
+/* Make the given directory including its parent directories as necessary.
+ * Return TRUE on success, FALSE on error. */
+static notmuch_bool_t
+make_directory_and_parents (char *path, int mode)
+{
+struct stat st;
+char *start;
+char *end;
+notmuch_bool_t ret;
+
+/* First check the common case: directory already exists. */
+if (stat (path, st) == 0)
+   return S_ISDIR (st.st_mode) ? TRUE : FALSE;
+
+for (start = path; *start != '\0'; start = end + 1) {
+   /* start points to the first unprocessed character.
+* Find the next slash from start onwards. */
+   end = strchr (start, '/');
+
+   /* If there are no more slashes then all the parent directories
+* have been made.  Now attempt to make the whole path. */
+   if (end == NULL)
+   return make_directory (path, mode);
+
+   /* Make the path up to the next slash, unless the current
+* directory component is actually empty. */
+   if (end  start) {
+   *end = '\0';
+   ret = make_directory (path, mode);
+   *end = '/';
+   if (! ret)
+   return FALSE;
+   }
+}
+
+return TRUE;
+}
+
+/* Create the given maildir folder, i.e. dir and its subdirectories
+ * 'cur', 'new', 'tmp'. */
+static notmuch_bool_t
+maildir_create_folder (void *ctx, const char *dir)
+{
+const int mode = 0700;
+char *subdir;
+char *tail;
+
+/* Create 'cur' directory, including parent directories. */
+subdir = talloc_asprintf (ctx, %s/cur, dir);
+if (! subdir) {
+   fprintf (stderr, Out of memory.\n);
+   return FALSE;
+}
+if (! make_directory_and_parents (subdir, mode))
+   return FALSE;
+
+tail = subdir + strlen (subdir) - 3;
+
+/* Create 'new' directory. */
+strcpy (tail, new);
+if (! make_directory (subdir, mode))
+   return FALSE;
+
+/* Create 'tmp' directory. */
+strcpy (tail, tmp);
+if (! make_directory (subdir, mode))
+   return FALSE;
+
+talloc_free (subdir);
+return TRUE;
+}
+
 /* Open a unique file in the Maildir 'tmp' directory.
  * Returns the file descriptor on success, or -1 on failure.
  * On success, file paths for the message in the 'tmp' and 'new'
@@ -254,6 +335,7 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
 tag_op_list_t *tag_ops;
 char *query_string = NULL;
 const char *folder = NULL;
+notmuch_bool_t create_folder = FALSE;
 char *maildir;
 int opt_index;
 unsigned int i;
@@ -261,6 +343,7 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
 
 notmuch_opt_desc_t options[] = {
{ NOTMUCH_OPT_STRING, folder, folder, 0, 0 },
+   { NOTMUCH_OPT_BOOLEAN, create_folder, create-folder, 0, 0 },
{ NOTMUCH_OPT_END, 0, 0, 0, 0 }
 };
 
@@ -311,6 +394,11 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
fprintf (stderr, Out of memory\n);
return 1;
 }
+if (create_folder  ! maildir_create_folder (ctx, maildir)) {
+   fprintf (stderr, Error: creating maildir %s: %s\n,
+maildir, strerror (errno));
+   return 1;
+}
 
 if (notmuch_database_open (notmuch_config_get_database_path (config),
   NOTMUCH_DATABASE_MODE_READ_WRITE, notmuch))
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 13/20] insert: fsync after writing tmp file

2013-01-19 Thread Peter Wang
Flush the tmp file to disk after writing for durability.
---
 notmuch-insert.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index 85acaea..60855c1 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -305,6 +305,10 @@ insert_message (void *ctx, notmuch_database_t *notmuch, 
int fdin,
return FALSE;
 }
 ret = copy_stdin (fdin, fdout);
+if (ret  fsync (fdout) != 0) {
+   fprintf (stderr, Error: fsync failed: %s\n, strerror (errno));
+   ret = FALSE;
+}
 close (fdout);
 if (ret) {
ret = maildir_move_tmp_to_new (tmppath, newpath);
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 14/20] insert: fsync new directory after rename

2013-01-19 Thread Peter Wang
After moving the file from the 'tmp' to the 'new' directory,
fsync on the 'new' directory for durability.
---
 notmuch-insert.c | 41 ++---
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index 60855c1..c4d5e75 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -56,6 +56,28 @@ check_folder_name (const char *folder)
 }
 }
 
+/* Call fsync() on a directory path. */
+static notmuch_bool_t
+sync_dir (const char *dir)
+{
+notmuch_bool_t ret;
+int fd;
+
+ret = TRUE;
+fd = open (dir, O_RDONLY);
+if (fd == -1) {
+   fprintf (stderr, Error: open() dir failed: %s\n, strerror (errno));
+   ret = FALSE;
+}
+if (ret  fsync (fd) != 0) {
+   fprintf (stderr, Error: fsync() dir failed: %s\n, strerror (errno));
+   ret = FALSE;
+}
+if (fd != -1)
+   close (fd);
+return ret;
+}
+
 /* Make the given directory, succeeding if it already exists. */
 static notmuch_bool_t
 make_directory (char *path, int mode)
@@ -140,10 +162,11 @@ maildir_create_folder (void *ctx, const char *dir)
 /* Open a unique file in the Maildir 'tmp' directory.
  * Returns the file descriptor on success, or -1 on failure.
  * On success, file paths for the message in the 'tmp' and 'new'
- * directories are returned via tmppath and newpath. */
+ * directories are returned via tmppath and newpath,
+ * and the path of the 'new' directory itself in newdir. */
 static int
 maildir_open_tmp_file (void *ctx, const char *dir,
-  char **tmppath, char **newpath)
+  char **tmppath, char **newpath, char **newdir)
 {
 pid_t pid;
 char hostname[256];
@@ -180,8 +203,9 @@ maildir_open_tmp_file (void *ctx, const char *dir,
return -1;
 }
 
+*newdir = talloc_asprintf (ctx, %s/new, dir);
 *newpath = talloc_asprintf (ctx, %s/new/%s, dir, filename);
-if (! *newpath) {
+if (! *newdir || ! *newpath) {
fprintf (stderr, Out of memory\n);
close (fd);
unlink (*tmppath);
@@ -201,14 +225,16 @@ maildir_open_tmp_file (void *ctx, const char *dir,
  * http://wiki.dovecot.org/MailboxFormat/Maildir#Mail_delivery
  */
 static notmuch_bool_t
-maildir_move_tmp_to_new (const char *tmppath, const char *newpath)
+maildir_move_tmp_to_new (const char *tmppath, const char *newpath,
+const char *newdir)
 {
 if (rename (tmppath, newpath) != 0) {
fprintf (stderr, Error: rename() failed: %s\n, strerror (errno));
return FALSE;
 }
 
-return TRUE;
+/* Sync the 'new' directory after rename for durability. */
+return sync_dir (newdir);
 }
 
 /* Copy the contents of standard input (fdin) into fdout. */
@@ -297,10 +323,11 @@ insert_message (void *ctx, notmuch_database_t *notmuch, 
int fdin,
 {
 char *tmppath;
 char *newpath;
+char *newdir;
 int fdout;
 notmuch_bool_t ret;
 
-fdout = maildir_open_tmp_file (ctx, dir, tmppath, newpath);
+fdout = maildir_open_tmp_file (ctx, dir, tmppath, newpath, newdir);
 if (fdout  0) {
return FALSE;
 }
@@ -311,7 +338,7 @@ insert_message (void *ctx, notmuch_database_t *notmuch, int 
fdin,
 }
 close (fdout);
 if (ret) {
-   ret = maildir_move_tmp_to_new (tmppath, newpath);
+   ret = maildir_move_tmp_to_new (tmppath, newpath, newdir);
 }
 if (!ret) {
unlink (tmppath);
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 15/20] insert: fsync parent directory after mkdir

2013-01-19 Thread Peter Wang
After creating a subdirectory, fsync on its parent directory for
durability.
---
 notmuch-insert.c | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index c4d5e75..8012eb4 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -82,9 +82,21 @@ sync_dir (const char *dir)
 static notmuch_bool_t
 make_directory (char *path, int mode)
 {
+notmuch_bool_t ret;
+char *slash;
+
 if (mkdir (path, mode) != 0)
return (errno == EEXIST);
-return TRUE;
+
+/* Sync the parent directory for durability. */
+ret = TRUE;
+slash = strrchr (path, '/');
+if (slash) {
+   *slash = '\0';
+   ret = sync_dir (path);
+   *slash = '/';
+}
+return ret;
 }
 
 /* Make the given directory including its parent directories as necessary.
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 16/20] insert: trap SIGINT and clean up

2013-01-19 Thread Peter Wang
The only potentially long-running part of the 'insert' command should be
copying stdin to the 'tmp' file.  If SIGINT is received during the
copying process, abort and clean up the file in 'tmp'.  At all other
points, just ignore the signal and continue.
---
 notmuch-insert.c | 28 ++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index 8012eb4..494a7b0 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -25,6 +25,21 @@
 #include sys/stat.h
 #include fcntl.h
 
+static volatile sig_atomic_t interrupted;
+
+static void
+handle_sigint (unused (int sig))
+{
+static char msg[] = Stopping... \n;
+
+/* This write is opportunistic, so it's okay to ignore the
+ * result.  It is not required for correctness, and if it does
+ * fail or produce a short write, we want to get out of the signal
+ * handler as quickly as possible, not retry it. */
+IGNORE_RESULT (write (2, msg, sizeof (msg) - 1));
+interrupted = 1;
+}
+
 /* Like gethostname but guarantees that a null-terminated hostname is
  * returned, even if it has to make one up.
  * Returns true unless hostname contains a slash. */
@@ -258,7 +273,7 @@ copy_stdin (int fdin, int fdout)
 ssize_t remain;
 ssize_t written;
 
-for (;;) {
+while (! interrupted) {
remain = read (fdin, buf, sizeof (buf));
if (remain == 0)
break;
@@ -287,7 +302,7 @@ copy_stdin (int fdin, int fdout)
} while (remain  0);
 }
 
-return TRUE;
+return ! interrupted;
 }
 
 /* Add the specified message file to the notmuch database, applying tags.
@@ -372,6 +387,7 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
 {
 notmuch_config_t *config;
 notmuch_database_t *notmuch;
+struct sigaction action;
 const char *db_path;
 const char **new_tags;
 size_t new_tags_length;
@@ -443,6 +459,14 @@ notmuch_insert_command (void *ctx, int argc, char *argv[])
return 1;
 }
 
+/* Setup our handler for SIGINT. We do not set SA_RESTART so that copying
+ * from standard input may be interrupted. */
+memset (action, 0, sizeof (struct sigaction));
+action.sa_handler = handle_sigint;
+sigemptyset (action.sa_mask);
+action.sa_flags = 0;
+sigaction (SIGINT, action, NULL);
+
 if (notmuch_database_open (notmuch_config_get_database_path (config),
   NOTMUCH_DATABASE_MODE_READ_WRITE, notmuch))
return 1;
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 17/20] insert: add copyright line from notmuch-deliver

2013-01-19 Thread Peter Wang
The 'insert' implementation was based partly on notmuch-deliver.
---
 notmuch-insert.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/notmuch-insert.c b/notmuch-insert.c
index 494a7b0..6b3e380 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -2,6 +2,9 @@
  *
  * Copyright © 2013 Peter Wang
  *
+ * Based in part on notmuch-deliver
+ * Copyright © 2010 Ali Polatel
+ *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 18/20] man: document 'insert' command

2013-01-19 Thread Peter Wang
Add initial documentation for notmuch insert command.
---
 man/Makefile.local|  1 +
 man/man1/notmuch-insert.1 | 59 +++
 2 files changed, 60 insertions(+)
 create mode 100644 man/man1/notmuch-insert.1

diff --git a/man/Makefile.local b/man/Makefile.local
index 72e2a18..216aaa0 100644
--- a/man/Makefile.local
+++ b/man/Makefile.local
@@ -12,6 +12,7 @@ MAN1 := \
$(dir)/man1/notmuch-count.1 \
$(dir)/man1/notmuch-dump.1 \
$(dir)/man1/notmuch-restore.1 \
+   $(dir)/man1/notmuch-insert.1 \
$(dir)/man1/notmuch-new.1 \
$(dir)/man1/notmuch-reply.1 \
$(dir)/man1/notmuch-search.1 \
diff --git a/man/man1/notmuch-insert.1 b/man/man1/notmuch-insert.1
new file mode 100644
index 000..4a7cbeb
--- /dev/null
+++ b/man/man1/notmuch-insert.1
@@ -0,0 +1,59 @@
+.TH NOTMUCH-INSERT 1 2013-xx-xx Notmuch 0.xx
+.SH NAME
+notmuch-insert \- add a message to the maildir and notmuch database
+.SH SYNOPSIS
+
+.B notmuch insert
+.RI [ options ]
+.RI [ + tag |\- tag  ... ]
+
+.SH DESCRIPTION
+
+.B notmuch insert
+reads a message from standard input
+and delivers it to the specified maildir folder,
+then incorporates the message into the notmuch database.
+It is an alternative to using a separate tool to deliver
+the message then running
+.B notmuch new
+afterwards.
+
+The new message will be tagged with the tags specified by the
+.B new.tags
+configuration option, then by operations specified on the command-line:
+tags prefixed by '+' are added while
+those prefixed by '\-' are removed.
+
+Option arguments must appear before any tag operation arguments.
+Supported options for
+.B insert
+include
+.RS 4
+.TP 4
+.BI --folder= folder 
+
+Deliver the message to the specified folder,
+relative to the top-level directory given by the value of
+\fBdatabase.path\fR.
+The default is to deliver to the top-level directory.
+
+.RE
+
+.RS 4
+.TP 4
+.B --create-folder
+
+Try to create the folder named by the
+.B --folder
+option, if it does not exist.
+Otherwise the folder must already exist for mail
+delivery to succeed.
+
+.RE
+.SH SEE ALSO
+
+\fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1),
+\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5), \fBnotmuch-reply\fR(1),
+\fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1),
+\fBnotmuch-search-terms\fR(7), \fBnotmuch-show\fR(1),
+\fBnotmuch-tag\fR(1)
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 20/20] test: add tests for insert

2013-01-19 Thread Peter Wang
Add tests for new 'insert' command.
---
 test/insert   | 106 ++
 test/notmuch-test |   1 +
 2 files changed, 107 insertions(+)
 create mode 100755 test/insert

diff --git a/test/insert b/test/insert
new file mode 100755
index 000..a3b6283
--- /dev/null
+++ b/test/insert
@@ -0,0 +1,106 @@
+#!/usr/bin/env bash
+test_description='notmuch insert'
+. ./test-lib.sh
+
+# Create directories and database before inserting.
+mkdir -p $MAIL_DIR/{cur,new,tmp}
+mkdir -p $MAIL_DIR/Drafts/{cur,new,tmp}
+notmuch new  /dev/null
+
+# We use generate_message to create the temporary message files.
+# They happen to be in the mail directory already but that is okay
+# since we do not call notmuch new hereafter.
+
+gen_insert_msg() {
+generate_message \
+   [subject]=\insert-subject\ \
+   [date]=\Sat, 01 Jan 2000 12:00:00 -\ \
+   [body]=\insert-message\
+}
+
+test_begin_subtest Insert message, copied exactly
+gen_insert_msg
+notmuch insert  $gen_msg_filename
+cur_msg_filename=$(notmuch search --output=files subject:insert-subject)
+test_expect_equal_file $cur_msg_filename $gen_msg_filename
+
+test_begin_subtest Insert message, default tags
+output=$(notmuch show --format=json subject:insert-subject)
+expected='[[[{
+ id: '${gen_msg_id}',
+ match: true,
+ excluded: false,
+ filename: '${cur_msg_filename}',
+ timestamp: 946728000,
+ date_relative: 2000-01-01,
+ tags: [inbox,unread],
+ headers: {
+  Subject: insert-subject,
+  From: Notmuch Test Suite test_su...@notmuchmail.org,
+  To: Notmuch Test Suite test_su...@notmuchmail.org,
+  Date: Sat, 01 Jan 2000 12:00:00 +},
+ body: [{id: 1,
+  content-type: text/plain,
+  content: insert-message\n}]},
+ ['
+test_expect_equal_json $output $expected
+
+test_begin_subtest Insert message, duplicate message
+notmuch insert  $gen_msg_filename
+output=$(notmuch search --output=files subject:insert-subject | wc -l)
+test_expect_equal $output 2
+
+test_begin_subtest Insert message, add tag
+gen_insert_msg
+notmuch insert +custom  $gen_msg_filename
+output=$(notmuch count tag:custom)
+test_expect_equal $output 1
+
+test_begin_subtest Insert message, add/remove tag
+gen_insert_msg
+notmuch insert +custom -unread  $gen_msg_filename
+output=$(notmuch count tag:custom NOT tag:unread)
+test_expect_equal $output 1
+
+test_begin_subtest Insert message, folder
+gen_insert_msg
+notmuch insert --folder=Drafts  $gen_msg_filename
+output=$(notmuch search --output=files folder:Drafts)
+dirname=$(dirname $output)
+test_expect_equal $dirname $MAIL_DIR/Drafts/cur
+
+test_begin_subtest Insert message, folder and tags
+gen_insert_msg
+notmuch insert --folder=Drafts +draft -unread  $gen_msg_filename
+output=$(notmuch count folder:Drafts tag:draft NOT tag:unread)
+test_expect_equal $output 1
+
+gen_insert_msg
+test_expect_code 1 Insert message, non-existent folder \
+notmuch insert --folder=nonesuch  $gen_msg_filename
+
+test_begin_subtest Insert message, create folder
+gen_insert_msg
+notmuch insert --folder=F --create-folder +folder  $gen_msg_filename
+output=$(notmuch search --output=files folder:F tag:folder)
+basename=$(basename $output)
+test_expect_equal_file $gen_msg_filename $MAIL_DIR/F/cur/${basename}
+
+test_begin_subtest Insert message, create subfolder
+gen_insert_msg
+notmuch insert --folder=F/G/H/I/J --create-folder +folder  $gen_msg_filename
+output=$(notmuch search --output=files folder:F/G/H/I/J tag:folder)
+basename=$(basename $output)
+test_expect_equal_file $gen_msg_filename 
${MAIL_DIR}/F/G/H/I/J/cur/${basename}
+
+test_begin_subtest Insert message, create existing subfolder
+gen_insert_msg
+notmuch insert --folder=F/G/H/I/J --create-folder +folder  $gen_msg_filename
+output=$(notmuch count folder:F/G/H/I/J tag:folder)
+test_expect_equal $output 2
+
+gen_insert_msg
+test_expect_code 1 Insert message, create invalid subfolder \
+notmuch insert --folder=../G --create-folder $gen_msg_filename
+
+test_done
diff --git a/test/notmuch-test b/test/notmuch-test
index ca9c3dc..6952f0a 100755
--- a/test/notmuch-test
+++ b/test/notmuch-test
@@ -22,6 +22,7 @@ TESTS=
   config
   new
   count
+  insert
   search
   search-output
   search-by-folder
-- 
1.7.12.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v3 19/20] man: reference notmuch-insert.1

2013-01-19 Thread Peter Wang
Add references to notmuch-insert.1 from other man pages.
---
 man/man1/notmuch-config.1   | 4 ++--
 man/man1/notmuch-count.1| 4 ++--
 man/man1/notmuch-dump.1 | 4 ++--
 man/man1/notmuch-new.1  | 4 ++--
 man/man1/notmuch-reply.1| 3 ++-
 man/man1/notmuch-restore.1  | 3 ++-
 man/man1/notmuch-search.1   | 3 ++-
 man/man1/notmuch-show.1 | 3 ++-
 man/man1/notmuch-tag.1  | 3 ++-
 man/man1/notmuch.1  | 3 ++-
 man/man5/notmuch-hooks.5| 4 ++--
 man/man7/notmuch-search-terms.7 | 3 ++-
 12 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/man/man1/notmuch-config.1 b/man/man1/notmuch-config.1
index 557eae5..e6d960d 100644
--- a/man/man1/notmuch-config.1
+++ b/man/man1/notmuch-config.1
@@ -152,7 +152,7 @@ use ${HOME}/.notmuch\-config if this variable is not set.
 .SH SEE ALSO
 
 \fBnotmuch\fR(1), \fBnotmuch-count\fR(1), \fBnotmuch-dump\fR(1),
-\fBnotmuch-hooks\fR(5), \fBnotmuch-new\fR(1), \fBnotmuch-reply\fR(1),
-\fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1),
+\fBnotmuch-hooks\fR(5), \fBnotmuch-insert\fR(1), \fBnotmuch-new\fR(1),
+\fBnotmuch-reply\fR(1), \fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1),
 \fBnotmuch-search-terms\fR(7), \fBnotmuch-show\fR(1),
 \fBnotmuch-tag\fR(1)
diff --git a/man/man1/notmuch-count.1 b/man/man1/notmuch-count.1
index d63be99..2651412 100644
--- a/man/man1/notmuch-count.1
+++ b/man/man1/notmuch-count.1
@@ -52,7 +52,7 @@ count (the default) or not.
 .SH SEE ALSO
 
 \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-dump\fR(1),
-\fBnotmuch-hooks\fR(5), \fBnotmuch-new\fR(1), \fBnotmuch-reply\fR(1),
-\fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1),
+\fBnotmuch-hooks\fR(5), \fBnotmuch-insert\fR(1), \fBnotmuch-new\fR(1),
+\fBnotmuch-reply\fR(1), \fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1),
 \fBnotmuch-search-terms\fR(7), \fBnotmuch-show\fR(1),
 \fBnotmuch-tag\fR(1)
diff --git a/man/man1/notmuch-dump.1 b/man/man1/notmuch-dump.1
index 613fd69..5e58cf9 100644
--- a/man/man1/notmuch-dump.1
+++ b/man/man1/notmuch-dump.1
@@ -92,7 +92,7 @@ for details of the supported syntax for search-terms.
 .SH SEE ALSO
 
 \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1),
-\fBnotmuch-hooks\fR(5), \fBnotmuch-new\fR(1), \fBnotmuch-reply\fR(1),
-\fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1),
+\fBnotmuch-hooks\fR(5), \fBnotmuch-insert\fR(1), \fBnotmuch-new\fR(1),
+\fBnotmuch-reply\fR(1), \fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1),
 \fBnotmuch-search-terms\fR(7), \fBnotmuch-show\fR(1),
 \fBnotmuch-tag\fR(1)
diff --git a/man/man1/notmuch-new.1 b/man/man1/notmuch-new.1
index 06c4dfa..e0ede8b 100644
--- a/man/man1/notmuch-new.1
+++ b/man/man1/notmuch-new.1
@@ -64,7 +64,7 @@ Prevents hooks from being run.
 .SH SEE ALSO
 
 \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1),
-\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5), \fBnotmuch-reply\fR(1),
-\fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1),
+\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5), \fBnotmuch-insert\fR(1),
+\fBnotmuch-reply\fR(1), \fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1),
 \fBnotmuch-search-terms\fR(7), \fBnotmuch-show\fR(1),
 \fBnotmuch-tag\fR(1)
diff --git a/man/man1/notmuch-reply.1 b/man/man1/notmuch-reply.1
index 13e50ad..82437a4 100644
--- a/man/man1/notmuch-reply.1
+++ b/man/man1/notmuch-reply.1
@@ -123,7 +123,8 @@ The requested format version is too new.
 .SH SEE ALSO
 
 \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1),
-\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5), \fBnotmuch-new\fR(1),
+\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5),
+\fBnotmuch-insert\fR(1), \fBnotmuch-new\fR(1),
 \fBnotmuch-restore\fR(1), \fBnotmuch-search\fR(1),
 \fBnotmuch-search-terms\fR(7), \fBnotmuch-show\fR(1),
 \fBnotmuch-tag\fR(1)
diff --git a/man/man1/notmuch-restore.1 b/man/man1/notmuch-restore.1
index 895c6d2..65ecfc8 100644
--- a/man/man1/notmuch-restore.1
+++ b/man/man1/notmuch-restore.1
@@ -84,7 +84,8 @@ should be accurate.
 .SH SEE ALSO
 
 \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1),
-\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5), \fBnotmuch-new\fR(1),
+\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5),
+\fBnotmuch-insert\fR(1), \fBnotmuch-new\fR(1),
 \fBnotmuch-reply\fR(1), \fBnotmuch-search\fR(1),
 \fBnotmuch-search-terms\fR(7), \fBnotmuch-show\fR(1),
 \fBnotmuch-tag\fR(1)
diff --git a/man/man1/notmuch-search.1 b/man/man1/notmuch-search.1
index 321d779..67fd34b 100644
--- a/man/man1/notmuch-search.1
+++ b/man/man1/notmuch-search.1
@@ -155,7 +155,8 @@ The requested format version is too new.
 .SH SEE ALSO
 
 \fBnotmuch\fR(1), \fBnotmuch-config\fR(1), \fBnotmuch-count\fR(1),
-\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5), \fBnotmuch-new\fR(1),
+\fBnotmuch-dump\fR(1), \fBnotmuch-hooks\fR(5),
+\fBnotmuch-insert\fR(1), \fBnotmuch-new\fR(1),
 \fBnotmuch-reply\fR(1), \fBnotmuch-restore\fR(1),
 \fBnotmuch-search-terms\fR(7), \fBnotmuch-show\fR(1),
 \fBnotmuch-tag\fR(1)
diff --git