From 50aaab91b5c19d50a33c5b89ebe92a39ff78283b Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Sat, 23 Sep 2023 08:12:06 -0300
Subject: [PATCH 01/18] version: update to 0.38.1~pre0

Start preparations for point release
---
 bindings/python/notmuch/version.py | 2 +-
 version.txt                        | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/bindings/python/notmuch/version.py b/bindings/python/notmuch/version.py
index c847a1a3..af97e6d1 100644
--- a/bindings/python/notmuch/version.py
+++ b/bindings/python/notmuch/version.py
@@ -1,3 +1,3 @@
 # this file should be kept in sync with ../../../version
-__VERSION__ = '0.38'
+__VERSION__ = '0.38.1~pre0'
 SOVERSION = '5'
diff --git a/version.txt b/version.txt
index 1cbc8125..cf30d88f 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-0.38
+0.38.1~pre0

From 14bc0cc56b19db927893a2fa4505bae232dd712b Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Sat, 23 Sep 2023 08:14:21 -0300
Subject: [PATCH 02/18] NEWS: add header for 0.38.1

Actual news items to be filled in after they are applied.
---
 NEWS | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/NEWS b/NEWS
index 00f4fe47..34bdfca2 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+Notmuch 0.38.1 (UNRELEASED)
+===========================
+
 Notmuch 0.38 (2023-09-12)
 =========================
 

From 6ed348474908e97950a78b431fdba19f528b2d30 Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Sat, 23 Sep 2023 08:16:20 -0300
Subject: [PATCH 03/18] debian: start changelog for 0.38.1~pre0-1

---
 debian/changelog | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index c2c2f6ab..eec70b05 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+notmuch (0.38.1~pre0-1) UNRELEASED; urgency=medium
+
+  * New upstream release release candidate
+
+ -- David Bremner <bremner@debian.org>  Sat, 23 Sep 2023 08:15:19 -0300
+
 notmuch (0.38-2) unstable; urgency=medium
 
   * Restrict autopkgtests to amd64 and aarch64. There are failures in

From 112c53535a569ba28a2a7f3baae7fcc4033c65bc Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Fri, 15 Sep 2023 09:50:01 -0300
Subject: [PATCH 04/18] test: add known broken test for bad utf8 in config

We should ideally print an informative error message, but at the very
least we should not exit with success.
---
 test/T030-config.sh | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/test/T030-config.sh b/test/T030-config.sh
index ea0b4012..c416e781 100755
--- a/test/T030-config.sh
+++ b/test/T030-config.sh
@@ -3,6 +3,8 @@
 test_description='"notmuch config"'
 . $(dirname "$0")/test-lib.sh || exit 1
 
+cp notmuch-config initial-config
+
 test_begin_subtest "Get string value"
 test_expect_equal "$(notmuch config get user.name)" "Notmuch Test Suite"
 
@@ -193,4 +195,10 @@ test_begin_subtest "get built_with.nonexistent prints false"
 output=$(notmuch config get built_with.nonexistent)
 test_expect_equal "$output" "false"
 
+test_begin_subtest "Bad utf8 reported as error"
+test_subtest_known_broken
+cp initial-config bad-config
+printf '[query]\nq3=from:\xff\n' >>bad-config
+test_expect_code 1 "notmuch --config=./bad-config config list"
+
 test_done

From dbb5ff338511bfa6718ed144b95a689809d4bea1 Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Fri, 15 Sep 2023 09:50:02 -0300
Subject: [PATCH 05/18] CLI: exit with error when load_config returns an error.

For now print a generic error message and exit with error on any
non-success code. Previously the code exited, but with exit code zero,
leading users / scripts to think the command had succeeded.
---
 notmuch.c           | 2 ++
 test/T030-config.sh | 1 -
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/notmuch.c b/notmuch.c
index 37286b8f..69a18131 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -584,6 +584,8 @@ main (int argc, char *argv[])
 	case NOTMUCH_STATUS_SUCCESS:
 	    break;
 	default:
+	    fputs ("Error: unable to load config file.\n", stderr);
+	    ret = 1;
 	    goto DONE;
 	}
 
diff --git a/test/T030-config.sh b/test/T030-config.sh
index c416e781..2d3017da 100755
--- a/test/T030-config.sh
+++ b/test/T030-config.sh
@@ -196,7 +196,6 @@ output=$(notmuch config get built_with.nonexistent)
 test_expect_equal "$output" "false"
 
 test_begin_subtest "Bad utf8 reported as error"
-test_subtest_known_broken
 cp initial-config bad-config
 printf '[query]\nq3=from:\xff\n' >>bad-config
 test_expect_code 1 "notmuch --config=./bad-config config list"

From bc38580cef3316254b1ffb15b4711b541c6f9bb3 Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Fri, 15 Sep 2023 09:50:03 -0300
Subject: [PATCH 06/18] test: add known broken subtest for the bad config error
 message

This is a bit fragile w.r.t. glib changing their error message, but it
already helped me find one formatting bug, so for now I think it's
worth it, instead of just grepping for "UTF-8".
---
 test/T030-config.sh | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/test/T030-config.sh b/test/T030-config.sh
index 2d3017da..636b5a53 100755
--- a/test/T030-config.sh
+++ b/test/T030-config.sh
@@ -200,4 +200,13 @@ cp initial-config bad-config
 printf '[query]\nq3=from:\xff\n' >>bad-config
 test_expect_code 1 "notmuch --config=./bad-config config list"
 
+test_begin_subtest "Specific error message about bad utf8"
+test_subtest_known_broken
+notmuch --config=./bad-config config list 2>ERRORS
+cat <<EOF > EXPECTED
+GLib: Key file contains key “q3” with value “from:�” which is not UTF-8
+Error: unable to load config file.
+EOF
+test_expect_equal_file EXPECTED ERRORS
+
 test_done

From 1c10d91d8e4a3e5bc76ca4c6b9939f3759e6ef5e Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Fri, 15 Sep 2023 09:50:04 -0300
Subject: [PATCH 07/18] Pass error message from GLib ini parser to CLI

The function _notmuch_config_load_from_file is only called in two
places in open.cc. Update internal API to match the idiom in open.cc.
Adding a newline is needed for consistency with other status strings.

Based in part on a patch [1] from Eric Blake.

[1]: id:20230906153402.101471-1-eblake@redhat.com
---
 lib/config.cc         | 13 +++++++++++--
 lib/notmuch-private.h |  2 +-
 lib/open.cc           |  4 ++--
 notmuch.c             |  6 ++++++
 test/T030-config.sh   |  1 -
 5 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/lib/config.cc b/lib/config.cc
index 2323860d..6cd15fab 100644
--- a/lib/config.cc
+++ b/lib/config.cc
@@ -416,7 +416,8 @@ _expand_path (void *ctx, const char *key, const char *val)
 
 notmuch_status_t
 _notmuch_config_load_from_file (notmuch_database_t *notmuch,
-				GKeyFile *file)
+				GKeyFile *file,
+				char **status_string)
 {
     notmuch_status_t status = NOTMUCH_STATUS_SUCCESS;
     gchar **groups = NULL, **keys, *val;
@@ -435,6 +436,7 @@ _notmuch_config_load_from_file (notmuch_database_t *notmuch,
 	for (gchar **keys_p = keys; *keys_p; keys_p++) {
 	    char *absolute_key = talloc_asprintf (notmuch, "%s.%s", *grp,  *keys_p);
 	    char *normalized_val;
+	    GError *gerr = NULL;
 
 	    /* If we opened from a given path, do not overwrite it */
 	    if (strcmp (absolute_key, "database.path") == 0 &&
@@ -442,7 +444,14 @@ _notmuch_config_load_from_file (notmuch_database_t *notmuch,
 		notmuch->xapian_db)
 		continue;
 
-	    val = g_key_file_get_string (file, *grp, *keys_p, NULL);
+	    val = g_key_file_get_string (file, *grp, *keys_p, &gerr);
+	    if (gerr) {
+		if (status_string)
+		    IGNORE_RESULT (asprintf (status_string,
+					     "GLib: %s\n",
+					     gerr->message));
+		g_error_free (gerr);
+	    }
 	    if (! val) {
 		status = NOTMUCH_STATUS_FILE_ERROR;
 		goto DONE;
diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index c19ee8e2..367e23e6 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -726,7 +726,7 @@ notmuch_status_t
 _notmuch_config_load_from_database (notmuch_database_t *db);
 
 notmuch_status_t
-_notmuch_config_load_from_file (notmuch_database_t *db, GKeyFile *file);
+_notmuch_config_load_from_file (notmuch_database_t *db, GKeyFile *file, char **status_string);
 
 notmuch_status_t
 _notmuch_config_load_defaults (notmuch_database_t *db);
diff --git a/lib/open.cc b/lib/open.cc
index 54d1faf3..005872dc 100644
--- a/lib/open.cc
+++ b/lib/open.cc
@@ -555,7 +555,7 @@ _finish_open (notmuch_database_t *notmuch,
 	    goto DONE;
 
 	if (key_file)
-	    status = _notmuch_config_load_from_file (notmuch, key_file);
+	    status = _notmuch_config_load_from_file (notmuch, key_file, &message);
 	if (status)
 	    goto DONE;
 
@@ -961,7 +961,7 @@ notmuch_database_load_config (const char *database_path,
     }
 
     if (key_file) {
-	status = _notmuch_config_load_from_file (notmuch, key_file);
+	status = _notmuch_config_load_from_file (notmuch, key_file, &message);
 	if (status)
 	    goto DONE;
     }
diff --git a/notmuch.c b/notmuch.c
index 69a18131..814b9e42 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -563,6 +563,12 @@ main (int argc, char *argv[])
 					       NULL,
 					       &notmuch,
 					       &status_string);
+	if (status_string) {
+	    fputs (status_string, stderr);
+	    free (status_string);
+	    status_string = NULL;
+	}
+
 	switch (status) {
 	case NOTMUCH_STATUS_NO_CONFIG:
 	    if (! (command->mode & NOTMUCH_COMMAND_CONFIG_CREATE)) {
diff --git a/test/T030-config.sh b/test/T030-config.sh
index 636b5a53..621e0b69 100755
--- a/test/T030-config.sh
+++ b/test/T030-config.sh
@@ -201,7 +201,6 @@ printf '[query]\nq3=from:\xff\n' >>bad-config
 test_expect_code 1 "notmuch --config=./bad-config config list"
 
 test_begin_subtest "Specific error message about bad utf8"
-test_subtest_known_broken
 notmuch --config=./bad-config config list 2>ERRORS
 cat <<EOF > EXPECTED
 GLib: Key file contains key “q3” with value “from:�” which is not UTF-8

From b1129d905af5643ffec6a19d6cb1cf76abf9d9ce Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Sun, 24 Sep 2023 06:51:49 -0300
Subject: [PATCH 08/18] emacs: save undisplayer function for MIME parts

For some kinds of MIME parts (at least images), our trickery with
overlays will not work, so save the more drastic function created by
Gnus that actually deletes the part from the buffer. In an ideal world
we would return this function as (part of) a value, but here the call
stack is too complicated for anything that simple, so we stash it in
the part plist and rely on that being preserved (unlike the mm handle,
which is transient).
---
 emacs/notmuch-lib.el | 1 +
 1 file changed, 1 insertion(+)

diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el
index 84ba8c5e..a09f4ab8 100644
--- a/emacs/notmuch-lib.el
+++ b/emacs/notmuch-lib.el
@@ -703,6 +703,7 @@ current buffer, if possible."
 	  (when (mm-inlinable-p handle)
 	    (set-buffer display-buffer)
 	    (mm-display-part handle)
+	    (plist-put part :undisplayer (mm-handle-undisplayer handle))
 	    t))))))
 
 ;;; Generic Utilities

From bfcfa947f8a989594d73a40a056cbb0bd37188ab Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Sun, 24 Sep 2023 06:51:50 -0300
Subject: [PATCH 09/18] emacs/show: save redisplay redisplay data when showing
 lazy part.

This data will be used to redisplay an image that is hidden by
deleting it from the buffer.  We cannot easily delay until the image
is hidden, as we won't have the original data at that point.
---
 emacs/notmuch-show.el | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 36cce619..107ce1b8 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -1019,10 +1019,13 @@ will return nil if the CID is unknown or cannot be retrieved."
 	   (part-end (copy-marker (point) t))
 	   ;; We have to save the depth as we can't find the depth
 	   ;; when narrowed.
-	   (depth (notmuch-show-get-depth)))
+	   (depth (notmuch-show-get-depth))
+	   (mime-type (plist-get (cadr part-args) :computed-type)))
       (save-restriction
 	(narrow-to-region part-beg part-end)
 	(delete-region part-beg part-end)
+	(when (and mime-type (string-match "^image/" mime-type))
+	  (button-put button :notmuch-redisplay-data part-args))
 	(apply #'notmuch-show-insert-bodypart-internal part-args)
 	(indent-rigidly part-beg
 			part-end

From 0646d4855bff8b1f7ab10d5207cd66c9e75ea810 Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Sun, 24 Sep 2023 06:51:51 -0300
Subject: [PATCH 10/18] emacs: save image redisplay data during non-lazy
 display

This data will eventually be used to redisplay hidden images. A
certain amount of refactoring is done here to avoid code
duplication.
---
 emacs/notmuch-show.el | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 107ce1b8..54cf00c6 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -1109,14 +1109,18 @@ is t, hide the part initially and show the button."
 			     (and deep button)
 			     (and high button)
 			     (and long button))))
-	 (content-beg (point)))
+	 (content-beg (point))
+	 (part-data (list msg part mime-type nth depth button)))
     ;; Store the computed mime-type for later use (e.g. by attachment handlers).
     (plist-put part :computed-type mime-type)
-    (if show-part
-	(notmuch-show-insert-bodypart-internal msg part mime-type nth depth button)
+    (cond
+     (show-part
+      (apply #'notmuch-show-insert-bodypart-internal part-data)
+      (when (and button (string-match "^image/" mime-type))
+	(button-put button :notmuch-redisplay-data part-data)))
+     (t
       (when button
-	(button-put button :notmuch-lazy-part
-		    (list msg part mime-type nth depth button))))
+	(button-put button :notmuch-lazy-part part-data))))
     ;; Some of the body part handlers leave point somewhere up in the
     ;; part, so we make sure that we're down at the end.
     (goto-char (point-max))

From a064a25427f466c6ba7da76c2b58bbac290caf5a Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Sun, 24 Sep 2023 06:51:52 -0300
Subject: [PATCH 11/18] emacs/show: special case toggling display of images

According to emacs upstream [1], we can't expect overlay invisibility
and images to get along. This commit uses the previously stashed
undisplayer functions to actually remove the images from the buffer.
When the image is toggled, it is essentially redisplayed from scratch,
using the previously stashed redisplay data.

[1]: https://lists.gnu.org/archive/html/emacs-devel/2023-08/msg00593.html
---
 emacs/notmuch-show.el | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 54cf00c6..4cc5aa57 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -644,8 +644,24 @@ message at DEPTH in the current thread."
 		(when show
 		  (button-put button :notmuch-lazy-part nil)
 		  (notmuch-show-lazy-part lazy-part button))
-	      ;; else there must be an overlay.
-	      (overlay-put overlay 'invisible (not show))
+	      (let* ((part (plist-get properties :notmuch-part))
+		     (undisplayer (plist-get part :undisplayer))
+		     (mime-type (plist-get part :computed-type))
+		     (redisplay-data (button-get button
+						 :notmuch-redisplay-data))
+		     (imagep (string-match "^image/" mime-type)))
+		(cond
+		 ((and imagep (not show) undisplayer)
+		  ;; call undisplayer thunk created by gnus.
+		  (funcall undisplayer)
+		  ;; there is an extra newline left
+		  (delete-region
+		   (+ 1 (button-end button))
+		   (+ 2 (button-end button))))
+		 ((and imagep show redisplay-data)
+		  (notmuch-show-lazy-part redisplay-data button))
+		 (t
+		  (overlay-put overlay 'invisible (not show)))))
 	      t)))))))
 
 ;;; Part content ID handling

From 6ea0b18d1ebf9198d72b40ebec2172a66af3509a Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Sun, 1 Oct 2023 08:16:48 -0300
Subject: [PATCH 12/18] debian: finalize changelog for 0.38.1~pre0-1

Bonus typo fix.
---
 debian/changelog | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index eec70b05..799f50db 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,8 @@
-notmuch (0.38.1~pre0-1) UNRELEASED; urgency=medium
+notmuch (0.38.1~pre0-1) experimental; urgency=medium
 
-  * New upstream release release candidate
+  * New upstream release candidate
 
- -- David Bremner <bremner@debian.org>  Sat, 23 Sep 2023 08:15:19 -0300
+ -- David Bremner <bremner@debian.org>  Sun, 01 Oct 2023 08:14:17 -0300
 
 notmuch (0.38-2) unstable; urgency=medium
 

From 72de64034d991c5d77de2f2212a91237748a2c0f Mon Sep 17 00:00:00 2001
From: Paul Wise <pabs3@bonedaddy.net>
Date: Thu, 12 Oct 2023 16:14:44 +0800
Subject: [PATCH 13/18] notmuch-mutt: fix Perl syntax of hash index lookups

Fixes: commit 239fdbbbf0cbd6cd6ebafb87e88cdb3cded75364
---
 contrib/notmuch-mutt/notmuch-mutt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contrib/notmuch-mutt/notmuch-mutt b/contrib/notmuch-mutt/notmuch-mutt
index 1ac68065..b81252c8 100755
--- a/contrib/notmuch-mutt/notmuch-mutt
+++ b/contrib/notmuch-mutt/notmuch-mutt
@@ -67,7 +67,7 @@ sub check_search_cache_maildir($) {
     foreach my $d (@contents) {
         -l "$maildir/$d" and die_dir( $maildir, "contains symlink $d");
         -d "$maildir/$d" or die_dir( $maildir, "contains non-directory $d");
-        exists($required[$d]) or die_dir( $maildir, "contains directory $d");
+        exists($required{$d}) or die_dir( $maildir, "contains directory $d");
     }
 }
 

From 4fc79eb196d4495a70a0e6eeeba247988f2be78d Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Thu, 12 Oct 2023 19:52:42 -0300
Subject: [PATCH 14/18] version: update to 0.38.1~rc1

---
 bindings/python/notmuch/version.py | 2 +-
 version.txt                        | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/bindings/python/notmuch/version.py b/bindings/python/notmuch/version.py
index af97e6d1..e654ab7f 100644
--- a/bindings/python/notmuch/version.py
+++ b/bindings/python/notmuch/version.py
@@ -1,3 +1,3 @@
 # this file should be kept in sync with ../../../version
-__VERSION__ = '0.38.1~pre0'
+__VERSION__ = '0.38.1~rc1'
 SOVERSION = '5'
diff --git a/version.txt b/version.txt
index cf30d88f..ba1bb575 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-0.38.1~pre0
+0.38.1~rc1

From 23ac959040557de3bb3ac4f07efa98ec5371beeb Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Thu, 12 Oct 2023 19:54:07 -0300
Subject: [PATCH 15/18] changelog for 0.38.1~rc1-1

---
 debian/changelog | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 799f50db..e9b1fec5 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+notmuch (0.38.1~rc1-1) experimental; urgency=medium
+
+  * New upstream release candidate
+
+ -- David Bremner <bremner@debian.org>  Thu, 12 Oct 2023 19:53:10 -0300
+
 notmuch (0.38.1~pre0-1) experimental; urgency=medium
 
   * New upstream release candidate

From 551ec61118fcf0c2c2960aeced1eaae69df995e0 Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Thu, 26 Oct 2023 19:45:04 -0300
Subject: [PATCH 16/18] version: bump to 0.38.1

No changes from 0.38.1~rc1
---
 bindings/python/notmuch/version.py | 2 +-
 version.txt                        | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/bindings/python/notmuch/version.py b/bindings/python/notmuch/version.py
index e654ab7f..1779d8cc 100644
--- a/bindings/python/notmuch/version.py
+++ b/bindings/python/notmuch/version.py
@@ -1,3 +1,3 @@
 # this file should be kept in sync with ../../../version
-__VERSION__ = '0.38.1~rc1'
+__VERSION__ = '0.38.1'
 SOVERSION = '5'
diff --git a/version.txt b/version.txt
index ba1bb575..bb22182d 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-0.38.1~rc1
+0.38.1

From e3bde388d86fd067dbf66356d079ec5c37b6029a Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Thu, 26 Oct 2023 19:52:27 -0300
Subject: [PATCH 17/18] NEWS: News for 0.38.1

Just note the 3 bug fixes.
---
 NEWS | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/NEWS b/NEWS
index 34bdfca2..a7c67445 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,21 @@
-Notmuch 0.38.1 (UNRELEASED)
+Notmuch 0.38.1 (2023-10-26)
 ===========================
 
+CLI
+---
+
+Report parse errors in config files.
+
+Emacs
+-----
+
+Fix image toggling for Emacs >= 29.1.
+
+notmuch-mutt
+------------
+
+Fix syntax error in script.
+
 Notmuch 0.38 (2023-09-12)
 =========================
 

From 356ad392716d2a775e58d766c1fec9047cc84163 Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Thu, 26 Oct 2023 20:02:05 -0300
Subject: [PATCH 18/18] debian: update changelog for 0.38.1-1

---
 debian/changelog | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index e9b1fec5..1a333385 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+notmuch (0.38.1-1) unstable; urgency=medium
+
+  * New upstream bugfix release
+
+ -- David Bremner <bremner@debian.org>  Thu, 26 Oct 2023 19:58:42 -0300
+
 notmuch (0.38.1~rc1-1) experimental; urgency=medium
 
   * New upstream release candidate