summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-12-21 23:38:42 +0200
committerSergey Poznyakoff <gray@gnu.org>2020-12-21 23:38:42 +0200
commit317bb197a7f288aa4d36d4af7849e90e14fd7a77 (patch)
tree583771cfe7e614587685e97b8feddd1eb66fbcdd
parent35b8dcfbe745d59faa4fde8d76b30c5781d5cd8d (diff)
downloadmailutils-317bb197a7f288aa4d36d4af7849e90e14fd7a77.tar.gz
mailutils-317bb197a7f288aa4d36d4af7849e90e14fd7a77.tar.bz2
MH: provide a mh_profile setting to control assignment of sequence numbers
The "Volatile-uidnext" setting controls how sequence numbers are allocated. By default they increase monotonically. If Volatile-uidnext is set to "true", each new incorporated message is assigned the sequence number equal to that of the last message increased by one. When the last message in the mailbox is deleted, the value of UIDNEXT is recalculated and UIDVALIDITY is increased. This follows the behavior of traditional MH implementations. * doc/texinfo/mu-mh.texi: Document chnges. * include/mailutils/sys/amd.h (MU_AMD_VOLATILE_UIDNEXT): New constant. * libmailutils/base/amd.c (amd_expunge): Reset uidvalidity and uidnext if MU_AMD_VOLATILE_UIDNEXT capability is set and the last message was removed. * libproto/mh/mh.c (_mailbox_mh_init): New mh_profile setting "Volatile-uidnext". If set to true, it instructs mailutils to mimic the traditional MH behavior when assigning sequence number to the new message. * testsuite/mbop.c (main): Use MBOP_PRE_OPEN_HOOK (if defined) as the name of the function to call before opening the mailbox. * libproto/mh/tests/mbop.c (mbop_pre_open_hook): New function. If the MH environment variable is set, take its value as the name of the mh_profile and read settings from it. * libproto/mh/tests/Makefile.am: Add uidvol.at * libproto/mh/tests/atlocal.in: Unset MH. * libproto/mh/tests/testsuite.at: Include uidvol.at * libproto/mh/tests/uidvol.at: New file.
-rw-r--r--doc/texinfo/mu-mh.texi21
-rw-r--r--include/mailutils/sys/amd.h9
-rw-r--r--libmailutils/base/amd.c21
-rw-r--r--libproto/mh/mh.c14
-rw-r--r--libproto/mh/tests/Makefile.am3
-rw-r--r--libproto/mh/tests/atlocal.in1
-rw-r--r--libproto/mh/tests/mbop.c27
-rw-r--r--libproto/mh/tests/testsuite.at1
-rw-r--r--libproto/mh/tests/uidvol.at72
-rw-r--r--testsuite/mbop.c5
10 files changed, 169 insertions, 5 deletions
diff --git a/doc/texinfo/mu-mh.texi b/doc/texinfo/mu-mh.texi
index 840ddc347..29b35848a 100644
--- a/doc/texinfo/mu-mh.texi
+++ b/doc/texinfo/mu-mh.texi
@@ -26,6 +26,27 @@ distribution directory.
@subsection Major differences between Mailutils MH and other MH implementations
@enumerate 1
+@item Sequence numbers increase monotonically;
+
+Message sequence numbers are used as UIDs and thus increase
+monotonically. This means, in particular, that if your
+inbox has messages in the range @samp{@var{X}--@var{Y}} and you
+delete all messages and then incorporate new mail, the first
+incorporated message will be assigned sequence number @samp{@var{Y} + 1}
+(other MH implementations will assign @samp{1}). If this behavior
+bugs you, add the following setting to your @file{.mh_profile}:
+
+@example
+Volatile-uidnext: true
+@end example
+
+You can always renumber your messages starting from @samp{1} by
+running
+
+@example
+folder -pack=1
+@end example
+
@item UUCP addresses are not supported;
@item Mailutils supports a set of new format specifications
diff --git a/include/mailutils/sys/amd.h b/include/mailutils/sys/amd.h
index 2affcba50..34076e11f 100644
--- a/include/mailutils/sys/amd.h
+++ b/include/mailutils/sys/amd.h
@@ -66,7 +66,14 @@ struct _amd_message
};
/* AMD capabilities */
-#define MU_AMD_STATUS 0x01 /* format keeps status flags */
+#define MU_AMD_STATUS 0x01 /* format keeps status flags */
+#define MU_AMD_VOLATILE_UIDNEXT 0x02 /* Reset UIDNEXT and UIDVALIDITY
+ when the last message is removed. This helps implement the traditional
+ MH behavior: sequence number for the new message is computed as that of
+ the last message incremented by one. Normally this behavior is enabled
+ by setting the 'Volatile-uidnext' parameter in mh_profile to 'true'.
+ See _mailbox_mh_init in libproto/mh/mh.c.
+*/
#define MU_AMD_F_INIT_SCAN 0x01 /* Done initial scanning */
#define MU_AMD_F_PROP 0x02 /* prop file existed */
diff --git a/libmailutils/base/amd.c b/libmailutils/base/amd.c
index ee32d2917..52531536f 100644
--- a/libmailutils/base/amd.c
+++ b/libmailutils/base/amd.c
@@ -1410,7 +1410,16 @@ amd_expunge (mu_mailbox_t mailbox)
if (expcount)
{
+ int reset_uidvalidity;
+
last_expunged++;
+
+ /* See the description of MU_AMD_VOLATILE_UIDNEXT in amd.h for
+ details.
+ */
+ reset_uidvalidity = (amd->capabilities & MU_AMD_VOLATILE_UIDNEXT)
+ && last_expunged == amd->msg_count;
+
do
{
size_t j;
@@ -1425,6 +1434,18 @@ amd_expunge (mu_mailbox_t mailbox)
;
}
while (last_expunged);
+
+ if (reset_uidvalidity)
+ {
+ /*
+ * The following is equivalent to
+ * mu_mailbox_uidvalidity_reset (amd->mailbox);
+ */
+
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+ amd_set_uidvalidity (amd->mailbox, tv.tv_sec);
+ }
}
if (updated && !amd->mailbox_size)
diff --git a/libproto/mh/mh.c b/libproto/mh/mh.c
index 338ea95f1..f83b69027 100644
--- a/libproto/mh/mh.c
+++ b/libproto/mh/mh.c
@@ -503,7 +503,8 @@ _mailbox_mh_init (mu_mailbox_t mailbox)
{
int rc;
struct _amd_data *amd;
-
+ char const *p;
+
rc = amd_init_mailbox (mailbox, sizeof (struct _amd_data), &amd);
if (rc)
return rc;
@@ -526,7 +527,16 @@ _mailbox_mh_init (mu_mailbox_t mailbox)
if (mu_mhprop_get_value (mu_mh_profile, "rmmproc", NULL))
amd->delete_msg = _mh_msg_delete;
-
+
+ if ((p = mu_mhprop_get_value (mu_mh_profile, "volatile-uidnext", NULL)) != NULL)
+ {
+ int res;
+ if (mu_str_to_c (p, mu_c_bool, &res, NULL))
+ mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR,
+ ("Value of Volatile-UIDNEXT is not a boolean"));
+ else if (res)
+ amd->capabilities |= MU_AMD_VOLATILE_UIDNEXT;
+ }
return 0;
}
diff --git a/libproto/mh/tests/Makefile.am b/libproto/mh/tests/Makefile.am
index fae4351e1..5e4bae891 100644
--- a/libproto/mh/tests/Makefile.am
+++ b/libproto/mh/tests/Makefile.am
@@ -47,7 +47,8 @@ TESTSUITE_AT += \
qget.at\
uid.at\
uidnext.at\
- uidvalidity.at
+ uidvalidity.at\
+ uidvol.at
diff --git a/libproto/mh/tests/atlocal.in b/libproto/mh/tests/atlocal.in
index fd440e2ad..f1a08c563 100644
--- a/libproto/mh/tests/atlocal.in
+++ b/libproto/mh/tests/atlocal.in
@@ -4,3 +4,4 @@
PATH=@abs_builddir@:@abs_top_builddir@/testsuite:$PATH
spooldir=$abs_top_srcdir/testsuite/spool/
+unset MH
diff --git a/libproto/mh/tests/mbop.c b/libproto/mh/tests/mbop.c
index 790c72773..3918adbab 100644
--- a/libproto/mh/tests/mbop.c
+++ b/libproto/mh/tests/mbop.c
@@ -1,3 +1,30 @@
+#include <stdlib.h>
+#include <mailutils/alloc.h>
+#include <mailutils/property.h>
+#include <mailutils/diag.h>
+#include <mailutils/mh.h>
+
#define MBOP_RECORD mu_mh_record
#define MBOP_SCHEME "mh"
+#define MBOP_PRE_OPEN_HOOK mbop_pre_open_hook
+static void
+mbop_pre_open_hook (void)
+{
+ char *env = getenv ("MH");
+ if (env && env[0])
+ {
+ struct mu_mh_prop *mhprop;
+ int rc;
+
+ mhprop = mu_zalloc (sizeof (mhprop[0]));
+ mhprop->filename = env;
+ mhprop->ro = 0;
+ rc = mu_property_create_init (&mu_mh_profile, mu_mh_property_init, mhprop);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_property_create_init", env, rc);
+ exit (1);
+ }
+ }
+}
#include "testsuite/mbop.c"
diff --git a/libproto/mh/tests/testsuite.at b/libproto/mh/tests/testsuite.at
index 33b16c70e..8ce7d50a6 100644
--- a/libproto/mh/tests/testsuite.at
+++ b/libproto/mh/tests/testsuite.at
@@ -34,6 +34,7 @@ m4_include([notify.at])
m4_include([delete.at])
m4_include([uidnext.at])
+m4_include([uidvol.at])
# Local Variables:
# mode: autotest
diff --git a/libproto/mh/tests/uidvol.at b/libproto/mh/tests/uidvol.at
new file mode 100644
index 000000000..d03171169
--- /dev/null
+++ b/libproto/mh/tests/uidvol.at
@@ -0,0 +1,72 @@
+# GNU Mailutils -- a suite of utilities for electronic mail -*- autotest -*-
+# Copyright (C) 2020 Free Software Foundation, Inc.
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This library 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
+
+AT_SETUP([Volatile UIDs (traditional MH behavior)])
+
+# Create the test MH mailbox
+AT_CHECK([mbox2dir -m -p -v 10 -u inbox $spooldir/mbox1])
+
+# Check its current UID settings
+AT_CHECK([mbop -m inbox uidnext \; uidvalidity],
+[0],
+[uidnext: 6
+uidvalidity: 10
+])
+
+# Request traditional MH behavior.
+AT_DATA([mh_profile],
+[Volatile-uidnext: true
+])
+
+# Remove the penultimate message. This should not affect uidvalidity.
+AT_CHECK([MH=mh_profile mbop -m inbox 4 \; set_deleted \; expunge],
+[0],
+[4 current message
+4 set_deleted: OK
+expunge: OK
+])
+
+# Check if uidnext and uidvalidity remain the same.
+AT_CHECK([mbop -m inbox uidnext \; uidvalidity],
+[0],
+[uidnext: 6
+uidvalidity: 10
+])
+
+# Remove the last message. With Volatile-uidnext on, this will reset
+# uidnext to 4 (sequence number of the last message plus one) and
+# increase uidvalidity,
+AT_CHECK([MH=mh_profile mbop -m inbox 4 \; set_deleted \; expunge],
+[0],
+[4 current message
+4 set_deleted: OK
+expunge: OK
+])
+
+# Check if uidnext is computed correctly.
+AT_CHECK([MH=mh_profile mbop -m inbox uidnext],
+[0],
+[uidnext: 4
+])
+
+# Check that uidvalidity has changed.
+# FIXME: Better check that it has *increased*.
+AT_CHECK([MH=mh_profile mbop -m inbox uidvalidity | grep -v '^uid-validity:10$' | grep uid-validity || true])
+
+AT_CLEANUP
+
+
+
diff --git a/testsuite/mbop.c b/testsuite/mbop.c
index 1af0ebf6e..e3ee0f8d3 100644
--- a/testsuite/mbop.c
+++ b/testsuite/mbop.c
@@ -621,7 +621,10 @@ main (int argc, char **argv)
mbox_flags = MU_STREAM_READ;
else
mbox_flags = MU_STREAM_RDWR;
-
+
+#ifdef MBOP_PRE_OPEN_HOOK
+ MBOP_PRE_OPEN_HOOK ();
+#endif
MU_ASSERT (mu_mailbox_create_default (&env.mbx, env.mbxname));
MU_ASSERT (mu_mailbox_open (env.mbx, mbox_flags));

Return to:

Send suggestions and report system problems to the System administrator.