commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. mu-1-2-90-separate-argp-cfg


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. mu-1-2-90-separate-argp-cfg-286-g8ea9411
Date: Wed, 08 Jul 2009 15:07:56 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=8ea94114b3242ab560db0aa6092354b2d327e527

The branch, master has been updated
       via  8ea94114b3242ab560db0aa6092354b2d327e527 (commit)
      from  671cdfcc3c3fcaae6a70b7e1672cac86b09effe2 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 8ea94114b3242ab560db0aa6092354b2d327e527
Author: Sergey Poznyakoff <address@hidden>
Date:   Wed Jul 8 18:00:43 2009 +0300

    Implement the mu_mailbox_get_uidls function and --uidl option in movemail.
    
    * include/mailutils/mailbox.h (MU_UIDL_LENGH)
    (MU_UIDL_BUFFER_SIZE): New defines.
    (struct mu_uidl): New struct.
    (mu_mailbox_get_uidls): New prototype.
    * libproto/include/mailbox0.h (struct _mu_mailbox): New member
    _get_uidls.
    * libproto/pop/mbox.c: Implement _get_uidls.
    * libproto/pop/folder.c: Include mailutils/cctype.h.
    
    * mailbox/mailbox.c (mu_mailbox_get_uidls): New function.
    
    * movemail/movemail.c: Implement --uidl option: use UIDLs to avoid
    downloading same messages twice.  Based on the idea of Alfred M. Szmidt.
    Implement --verbose option.
    
    * libproto/imap/mbox.c: Fix comment.
    
    * NEWS: Update.
    * doc/texinfo/programs.texi: Update.

-----------------------------------------------------------------------

Summary of changes:
 NEWS                        |   15 ++++-
 doc/texinfo/programs.texi   |   21 +++++-
 include/mailutils/mailbox.h |   10 +++
 libproto/imap/mbox.c        |   16 +++---
 libproto/include/mailbox0.h |    1 +
 libproto/pop/folder.c       |    3 +-
 libproto/pop/mbox.c         |   71 +++++++++++++++++++---
 mailbox/mailbox.c           |   67 ++++++++++++++++++++-
 movemail/movemail.c         |  142 ++++++++++++++++++++++++++++++++++++++++---
 9 files changed, 312 insertions(+), 34 deletions(-)

diff --git a/NEWS b/NEWS
index b6babd8..8cd6cda 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU mailutils NEWS -- history of user-visible changes. 2009-05-25
+GNU mailutils NEWS -- history of user-visible changes. 2009-07-08
 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 
 2008, 2009 Free Software Foundation, Inc.
 See the end of file for copying conditions.
@@ -18,6 +18,15 @@ All MU client utilities make use of the user ticket file,
 New configuration file entities allow to modify user's personal
 namespace and visible home directory.
 
+* Movemail
+
+When called with the `--uidl' command line option, the utility tries
+to avoid copying the message if a message with the same UIDL already
+exists in the destination mailbox.
+
+The `--verbose' command line option enables outputting additional
+information.
+
 * API
 
 * Wicket/Ticket functions
@@ -50,6 +59,10 @@ The `remote+sendmail', `remote+prog' and `remote+smtp' 
mailbox formats
 are deprecated in favor of `sendmail', `prog' and `smtp',
 correspondingly.  
 
+** New functions
+
+- mu_mailbox_get_uidls
+
 ** Removed functions
 
 - mu_sieve_get_ticket
diff --git a/doc/texinfo/programs.texi b/doc/texinfo/programs.texi
index b18e5fa..15cad8e 100644
--- a/doc/texinfo/programs.texi
+++ b/doc/texinfo/programs.texi
@@ -1,5 +1,5 @@
 @c This is part of the GNU Mailutils manual.
address@hidden Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008
address@hidden Copyright (C) 
1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009
 @c Free Software Foundation, Inc.
 @c See file mailutils.texi for copying conditions.
 @comment *******************************************************************
@@ -4034,6 +4034,15 @@ If @var{bool} is @samp{true}, reverse message sorting 
order.
 If @var{bool} is @samp{true}, output information used by Emacs rmail interface.
 @end deffn
 
address@hidden {Movemail Config} uidl @var{bool}
+Avoid copying the message if a message with the same UIDL already
+exists in the destination mailbox.
address@hidden deffn
+
address@hidden {Movemail Config} verbose @var{level}
+Set verbosity level.
address@hidden deffn
+
 @multitable @columnfractions 0.3 0.6
 @headitem Statement @tab Reference
 @item debug         @tab @xref{Debug Statement}.
@@ -4147,9 +4156,6 @@ Preserve the source mailbox
 @itemx --reverse
 Reverse the sorting order
 
address@hidden --license
-Print GPL license and exit
-
 @item address@hidden
 Use given @var{program} as the external locker program.
 
@@ -4177,6 +4183,13 @@ Use specified URL as a mailspool directory
 @item address@hidden
 Enable (default) or disable TLS support
 
address@hidden -u
address@hidden --uidl
+Use UIDLs to avoid downloading the same message twice.
+
address@hidden -v
address@hidden --verbose
+Increase verbosity level.
 @end table
 
 @page
diff --git a/include/mailutils/mailbox.h b/include/mailutils/mailbox.h
index 6da847e..e3222af 100644
--- a/include/mailutils/mailbox.h
+++ b/include/mailutils/mailbox.h
@@ -66,6 +66,16 @@ extern int  mu_mailbox_sync            (mu_mailbox_t);
 extern int  mu_mailbox_save_attributes (mu_mailbox_t)
                                        __attribute__ ((deprecated));
 
+#define MU_UIDL_LENGTH 70
+#define MU_UIDL_BUFFER_SIZE (MU_UIDL_LENGTH+1)
+                                      
+struct mu_uidl
+{
+  size_t msgno;
+  char uidl[MU_UIDL_BUFFER_SIZE];
+};
+extern int  mu_mailbox_get_uidls       (mu_mailbox_t, mu_list_t *);
+
 /* Update and scanning.  */
 extern int  mu_mailbox_get_size        (mu_mailbox_t, mu_off_t *size);
 extern int  mu_mailbox_is_updated      (mu_mailbox_t);
diff --git a/libproto/imap/mbox.c b/libproto/imap/mbox.c
index 1ebf9ff..8aada6c 100644
--- a/libproto/imap/mbox.c
+++ b/libproto/imap/mbox.c
@@ -719,14 +719,14 @@ imap_scan (mu_mailbox_t mailbox, size_t msgno, size_t 
*pcount)
   return imap_scan0 (mailbox, msgno, pcount , 1);
 }
 
-/* Usually when this function is call it is because there is an oberver
-   attach an the client is try to build some sort of list/tree header
-   as the scanning progress.  But doing this for each message can be
-   time consuming and inefficient.  So we bundle all the request
-   into one and ask the server for everything "FETCH 1:*".  The good
-   side is that everything will be faster and we do not do lot of small
-   transcation but rather a big one.  The bad thing is that every thing
-   will be cache in the structure using a lot of memory.  */
+/* Normally this function is called when an observer is trying to build
+   some sort of list/tree header as the scanning progresses.  But doing
+   this for each message can be time consuming and inefficient.  So we
+   bundle all requests into one and ask the server for everything:
+   "FETCH 1:*".  The good side is that everything will be faster and we
+   do not do lots of small transcations, but rather a big one.  The bad
+   side is that everything will be cached in the structure using a lot of
+   memory.  */
 static int
 imap_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int notif)
 {
diff --git a/libproto/include/mailbox0.h b/libproto/include/mailbox0.h
index e292c42..8ff1672 100644
--- a/libproto/include/mailbox0.h
+++ b/libproto/include/mailbox0.h
@@ -74,6 +74,7 @@ struct _mu_mailbox
   int  (*_get_size)        (mu_mailbox_t, mu_off_t *);
 
   int  (*_quick_get_message) (mu_mailbox_t, mu_message_qid_t, mu_message_t *);
+  int  (*_get_uidls) (mu_mailbox_t, mu_list_t);
 };
 
 #ifdef __cplusplus
diff --git a/libproto/pop/folder.c b/libproto/pop/folder.c
index 5aa4dc0..db41d40 100644
--- a/libproto/pop/folder.c
+++ b/libproto/pop/folder.c
@@ -34,7 +34,8 @@
 #include <mailutils/auth.h>
 #include <mailutils/errno.h>
 #include <mailutils/mailbox.h>
-#include <mailutils/mutil.h>
+#include <mailutils/cstr.h>
+#include <mailutils/cctype.h>
 
 #include <folder0.h>
 #include <registrar0.h>
diff --git a/libproto/pop/mbox.c b/libproto/pop/mbox.c
index 76a04f7..5992559 100644
--- a/libproto/pop/mbox.c
+++ b/libproto/pop/mbox.c
@@ -55,6 +55,7 @@
 #include <mailutils/md5.h>
 #include <mailutils/io.h>
 #include <mailutils/mutil.h>
+#include <mailutils/cstr.h>
 #include <mailutils/cctype.h>
 
 #include <folder0.h>
@@ -417,6 +418,57 @@ pop_destroy (mu_mailbox_t mbox)
     }
 }
 
+static int
+pop_mbox_uidls (mu_mailbox_t mbox, mu_list_t list)
+{
+  pop_data_t mpd = mbox->data;
+  int status;
+
+  status = pop_writeline (mpd, "UIDL\r\n");
+  CHECK_ERROR (mpd, status);
+  MU_DEBUG (mbox->debug, MU_DEBUG_PROT, mpd->buffer);
+
+  status = pop_write (mpd);
+  CHECK_EAGAIN (mpd, status);
+
+  status = pop_read_ack (mpd);
+  CHECK_EAGAIN (mpd, status);
+  MU_DEBUG (mpd->mbox->debug, MU_DEBUG_PROT, mpd->buffer);
+
+  if (!mu_c_strncasecmp (mpd->buffer, "+OK", 3))
+    {
+      do
+       {
+         char *p;
+         size_t num;
+         struct mu_uidl *uidl;
+         
+         status = pop_read_ack (mpd);
+         MU_DEBUG (mpd->mbox->debug, MU_DEBUG_PROT, mpd->buffer);
+
+         num = strtoul (mpd->buffer, &p, 10);
+         if (*p == 0 || !mu_isblank (*p))
+           continue; /* FIXME: or error? */
+         p = mu_str_skip_class (p, MU_CTYPE_SPACE);
+         mu_rtrim_cset (p, "\r\n");
+
+         uidl = malloc (sizeof (uidl[0]));
+         if (!uidl)
+           {
+             status = ENOMEM;
+             break;
+           }
+         uidl->msgno = num;
+         strncpy (uidl->uidl, p, MU_UIDL_BUFFER_SIZE);
+         status = mu_list_append (list, uidl);
+       }
+      while (mpd->nl);
+    }
+  else
+    status = ENOSYS;
+  return status;
+}
+
 /*
   POP3 CAPA support.
  */
@@ -454,12 +506,16 @@ pop_parse_capa (pop_data_t mpd)
            mpd->capa |= CAPA_STLS;
        }
       while (mpd->nl);
+
+      if (mpd->capa & CAPA_UIDL)
+       mpd->mbox->_get_uidls = pop_mbox_uidls;
+  
       return status;
     }
   else
     {
       /* mu_error ("CAPA not implemented"); */ /* FIXME */
-      return -1;
+      return ENOSYS;
     }
 }
 
@@ -485,7 +541,6 @@ pop_capa (mu_mailbox_t mbox)
   return pop_parse_capa (mpd);
 }
 
-
 /* Simple User/pass authentication for pop. We ask for the info
    from the standard input.  */
 int
@@ -1074,7 +1129,7 @@ pop_get_message (mu_mailbox_t mbox, size_t msgno, 
mu_message_t *pmsg)
   /* Set the UIDL call on the message. */
   if (mpd->capa & CAPA_UIDL)
     mu_message_set_uidl (msg, pop_uidl, mpm);
-
+  
   /* Set the UID on the message. */
   mu_message_set_uid (msg, pop_uid, mpm);
 
@@ -1427,7 +1482,7 @@ pop_message_size (mu_message_t msg, size_t *psize)
   CLEAR_STATE (mpd);
 
   if (status != 0)
-    status = MU_ERR_PARSE;
+    return MU_ERR_PARSE;
 
   /* The size of the message is with the extra '\r' octet for everyline.
      Substract to get, hopefully, a good count.  */
@@ -1570,7 +1625,7 @@ pop_uid (mu_message_t msg,  size_t *puid)
   return 0;
 }
 
-/* Get the UIDL.  Client should be prepare since it may fail.  UIDL is
+/* Get the UIDL.  The client should be prepared, since it may fail.  UIDL is
    optional on many POP servers.
    FIXME:  We should check the "mpd->capa & CAPA_UIDL" and fall back to
    a md5 scheme ? Or maybe check for "X-UIDL" a la Qpopper ?  */
@@ -1582,14 +1637,12 @@ pop_uidl (mu_message_t msg, char *buffer, size_t 
buflen, size_t *pnwriten)
   int status = 0;
   void *func = (void *)pop_uidl;
   size_t num;
-  /* According to the RFC uidl's are no longer then 70 chars.  Still playit
-     safe  */
-  char uniq[128];
+  char uniq[MU_UIDL_BUFFER_SIZE];
 
   if (mpm == NULL)
     return EINVAL;
 
-  /* Is it cache ?  */
+  /* Is it cached ?  */
   if (mpm->uidl)
     {
       size_t len = strlen (mpm->uidl);
diff --git a/mailbox/mailbox.c b/mailbox/mailbox.c
index aeb22c6..fc62ab7 100644
--- a/mailbox/mailbox.c
+++ b/mailbox/mailbox.c
@@ -287,7 +287,7 @@ mu_mailbox_flush (mu_mailbox_t mbox, int expunge)
 {
   size_t i, total = 0;
   int status = 0;
-
+  
   if (!mbox)
     return EINVAL;
   if (!(mbox->flags & (MU_STREAM_RDWR|MU_STREAM_WRITE|MU_STREAM_APPEND)))
@@ -680,4 +680,67 @@ mu_mailbox_unlock (mu_mailbox_t mbox)
   mu_mailbox_get_locker (mbox, &lock);
   return mu_locker_unlock (lock);
 }
-  
+
+static void
+free_uidl (void *item)
+{
+  free (item);
+}
+
+int
+mu_mailbox_get_uidls (mu_mailbox_t mbox, mu_list_t *plist)
+{
+  mu_list_t list;
+  int status;
+
+  if (mbox == NULL)
+    return MU_ERR_MBX_NULL;
+  if (plist == NULL)
+    return EINVAL;
+  status = mu_list_create (&list);
+  if (status)
+    return status;
+  mu_list_set_destroy_item (list, free_uidl);
+  if (mbox->_get_uidls)
+    status = mbox->_get_uidls (mbox, list);
+  else
+    {
+      size_t i, total;
+
+      status = mu_mailbox_messages_count (mbox, &total);
+      if (status)
+       return status;
+      for (i = 1; i <= total; i++)
+       {
+         mu_message_t msg = NULL;
+         char buf[MU_UIDL_BUFFER_SIZE];
+         size_t n;
+         struct mu_uidl *uidl;
+         
+         status = mu_mailbox_get_message (mbox, i, &msg);
+         if (status)
+           break;
+         status = mu_message_get_uidl (msg, buf, sizeof (buf), &n);
+         if (status)
+           break;
+         uidl = malloc (sizeof (uidl[0]));
+         if (!uidl)
+           {
+             status = ENOMEM;
+             break;
+           }
+         uidl->msgno = i;
+         strncpy (uidl->uidl, strdup (buf), MU_UIDL_BUFFER_SIZE);
+         status = mu_list_append (list, uidl);
+         if (status)
+           {
+             free_uidl (uidl);
+             break;
+           }
+       }
+    }
+  *plist = list;
+  return status;
+}
+
+         
diff --git a/movemail/movemail.c b/movemail/movemail.c
index 30bfa9c..bacfd40 100644
--- a/movemail/movemail.c
+++ b/movemail/movemail.c
@@ -47,6 +47,12 @@ static struct argp_option options[] = {
   { "copy-permissions", 'P', NULL, 0,
     N_("Copy original mailbox permissions and ownership when applicable"),
     0 },
+  { "uidl", 'u', NULL, 0,
+    N_("Use UIDLs to avoid downloading the same message twice"),
+    0 },
+  { "verbose", 'v', NULL, 0,
+    N_("Increase verbosity level"),
+    0 },
   { NULL,      0, NULL, 0, NULL, 0 }
 };
 
@@ -54,6 +60,8 @@ static int reverse_order;
 static int preserve_mail; 
 static int emacs_mode;
 static int copy_meta;
+static int uidl_option;
+static int verbose_option;
 
 static error_t
 parse_opt (int key, char *arg, struct argp_state *state)
@@ -73,6 +81,14 @@ parse_opt (int key, char *arg, struct argp_state *state)
     case 'P':
       copy_meta = 1;
       break;
+
+    case 'u':
+      mu_argp_node_list_new (&lst, "uidl", "yes");
+      break;
+
+    case 'v':
+      verbose_option++;
+      break;
       
     case OPT_EMACS:
       mu_argp_node_list_new (&lst, "emacs", "yes");
@@ -109,6 +125,10 @@ struct mu_cfg_param movemail_cfg_param[] = {
     N_("Reverse message sorting order.") },
   { "emacs", mu_cfg_bool, &emacs_mode, 0, NULL,
     N_("Output information used by Emacs rmail interface.") },
+  { "uidl", mu_cfg_bool, &uidl_option, 0, NULL,
+    N_("Use UIDLs to avoid downloading the same message twice.") },
+  { "verbose", mu_cfg_int, &verbose_option, 0, NULL,
+    N_("Increase verbosity level.") },
   { NULL }
 };
 
@@ -227,14 +247,14 @@ move_message (mu_mailbox_t src, mu_mailbox_t dst, size_t 
msgno)
 
   if ((rc = mu_mailbox_get_message (src, msgno, &msg)) != 0)
     {
-      fprintf (stderr, _("Cannot read message %lu: %s\n"),
-              (unsigned long) msgno, mu_strerror (rc));
+      mu_error (_("Cannot read message %lu: %s"),
+               (unsigned long) msgno, mu_strerror (rc));
       return rc;
     }
   if ((rc = mu_mailbox_append_message (dst, msg)) != 0)
     {
-      fprintf (stderr, _("Cannot append message %lu: %s\n"),
-              (unsigned long) msgno, mu_strerror (rc));
+      mu_error (_("Cannot append message %lu: %s\n"),
+               (unsigned long) msgno, mu_strerror (rc));
       return rc;
     }
   if (!preserve_mail)
@@ -344,6 +364,36 @@ set_permissions (mu_mailbox_t mbox)
     exit (1);
 }
 
+static int
+_compare_uidls (const void *item, const void *value)
+{
+  const struct mu_uidl *a = item;
+  const struct mu_uidl *b = value;
+
+  return strcmp (a->uidl, b->uidl);
+}
+
+static int
+_compare_msgno (const void *item, const void *value)
+{
+  const struct mu_uidl *a = item;
+  const struct mu_uidl *b = value;
+
+  if (a->msgno < b->msgno)
+    return -1;
+  if (a->msgno > b->msgno)
+    return 1;
+  return 0;
+}
+
+static int
+msgno_in_list (mu_list_t list, size_t num)
+{
+  struct mu_uidl t;
+  t.msgno = num;
+  return mu_list_locate (list, &t, NULL) == 0;
+}  
+
 int
 main (int argc, char **argv)
 {
@@ -352,6 +402,8 @@ main (int argc, char **argv)
   int rc = 0;
   char *source_name, *dest_name;
   int flags;
+  mu_list_t src_uidl_list = NULL;
+  size_t msg_count = 0;
   
   /* Native Language Support */
   MU_APP_INIT_NLS ();
@@ -395,19 +447,91 @@ main (int argc, char **argv)
     set_permissions (source);
   
   open_mailbox (&dest, dest_name, MU_STREAM_RDWR | MU_STREAM_CREAT, NULL);
+
+  rc = mu_mailbox_messages_count (source, &total);
+  if (rc)
+    {
+      mu_error(_("Cannot count messages: %s"), mu_strerror (rc));
+      exit (1);
+    }
+  
+  if (verbose_option)
+    mu_diag_output (MU_DIAG_INFO,
+                   _("Number of messages in source mailbox: %lu"),
+                   (unsigned long) total);
+
+  if (uidl_option)
+    {
+      mu_iterator_t itr;
+      mu_list_t dst_uidl_list = NULL;
+
+      rc = mu_mailbox_get_uidls (source, &src_uidl_list);
+      if (rc)
+       die (source, _("Cannot get UIDLs"), rc);
+      rc = mu_mailbox_get_uidls (dest, &dst_uidl_list);
+      if (rc)
+       die (dest, _("Cannot get UIDLs"), rc);
+
+      mu_list_set_comparator (src_uidl_list, NULL);
+      mu_list_set_comparator (dst_uidl_list, _compare_uidls);
+      
+      mu_list_get_iterator (src_uidl_list, &itr);
+      for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
+          mu_iterator_next (itr))
+       {
+         struct mu_uidl *uidl;
+             
+         mu_iterator_current (itr, (void **)&uidl);
+         if (mu_list_locate (dst_uidl_list, uidl, NULL) == 0)
+           mu_list_remove (src_uidl_list, uidl);
+       }
+      mu_iterator_destroy (&itr);
+      mu_list_destroy (&dst_uidl_list);
+      mu_list_set_comparator (src_uidl_list, _compare_msgno);
+    }
   
-  mu_mailbox_messages_count (source, &total);
   if (reverse_order)
     {
-      for (i = total; rc == 0 && i > 0; i--)
-       rc = move_message (source, dest, i);
+      for (i = total; i > 0; i--)
+       {
+         if (src_uidl_list && !msgno_in_list (src_uidl_list, i))
+           {
+             if (verbose_option > 1)
+               mu_diag_output (MU_DIAG_INFO, _("Ignoring message %lu"),
+                               (unsigned long) i);
+             continue;
+           }
+         rc = move_message (source, dest, i);
+         if (rc == 0)
+           msg_count++;
+         else
+           break;
+       }
     }
   else
     {
-      for (i = 1; rc == 0 && i <= total; i++)
-       rc = move_message (source, dest, i);
+      for (i = 1; i <= total; i++)
+       {
+         if (src_uidl_list && !msgno_in_list (src_uidl_list, i))
+           {
+             if (verbose_option > 1)
+               mu_diag_output (MU_DIAG_INFO, _("Ignoring message %lu"),
+                               (unsigned long) i);
+             continue;
+           }
+         rc = move_message (source, dest, i);
+         if (rc == 0)
+           msg_count++;
+         else
+           break;
+       }
     }
   
+  if (verbose_option)
+    mu_diag_output (MU_DIAG_INFO,
+                   _("Number of processed messages: %lu"),
+                   (unsigned long) msg_count);
+  
   if (rc)
     return rc;
   


hooks/post-receive
-- 
GNU Mailutils




reply via email to

[Prev in Thread] Current Thread [Next in Thread]