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=eea2c4aa6f4383f3288ddc0c9e5084e36d31d9ac The branch, master has been updated via eea2c4aa6f4383f3288ddc0c9e5084e36d31d9ac (commit) from be9580f6db6b710e0cd67ca326cac794742a112c (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 eea2c4aa6f4383f3288ddc0c9e5084e36d31d9ac Author: Sergey Poznyakoff <g...@gnu.org> Date: Mon May 4 16:11:53 2015 +0300 mail: the "copy" command operates on files by default. Last argument is treated as a mailbox only if it begins with a mailbox scheme (mbox://, maildir://, etc). * mail/copy.c (append_to_mailbox) (append_to_file): New functions. (mail_copy0): Depending on whether mailbox scheme is specified, call one of the above functions. * doc/texinfo/programs.texi (mail): Fix documentation of the copy command. * mail/testsuite/mail/write.exp: Update line/character counts for [Ss]ave commands. ----------------------------------------------------------------------- Summary of changes: doc/texinfo/programs.texi | 17 ++- mail/copy.c | 235 ++++++++++++++++++++++++++++++++-------- mail/testsuite/mail/write.exp | 4 +- 3 files changed, 202 insertions(+), 54 deletions(-) diff --git a/doc/texinfo/programs.texi b/doc/texinfo/programs.texi index c7d10e5..ee90ef0 100644 --- a/doc/texinfo/programs.texi +++ b/doc/texinfo/programs.texi @@ -3236,11 +3236,18 @@ prints the message, immediately following last deleted one. @table @samp @item save [[@var{msglist}] @var{file}] @itemx s [[@var{msglist}] @var{file}] -Takes a message list and a file name and appends each message in turn to -the end of the file. The name of file and number of characters appended -to it is echoed on the terminal. Each saved message is marked for -deletion as if with @code{delete} command, unless the variable -@code{keepsave} is set. +Takes a message list and a file name or mailbox URL and appends each +message in turn to the end of that file or mailbox. Mailbox URLs +begin with mailbox type specifier, such as @samp{mbox://}, +@samp{maildir://}, etc. The name of file or mailbox and number of +lines and characters appended to it is echoed on the terminal. When +writing to file, the numbers represent exact number of lines and +characters appended to the file. When @var{file} specifies a mailbox, +these numbers may differ by the amount of lines/characters needed to +represent message envelope for that specific mailbox type. + +Each saved message is marked for deletion as if with @code{delete} +command, unless the variable @code{keepsave} is set. @item Save [@var{msglist}] @itemx S [@var{msglist}] Like @code{save}, but the file to append messages to is named after the diff --git a/mail/copy.c b/mail/copy.c index ccbef62..5d35af6 100644 --- a/mail/copy.c +++ b/mail/copy.c @@ -16,6 +16,7 @@ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ #include "mail.h" +#include <mailutils/locker.h> /* * c[opy] [file] @@ -23,59 +24,33 @@ * C[opy] [msglist] */ -/* - * mail_copy0() is shared between mail_copy() and mail_save(). - * argc, argv -- argument count & vector - * mark -- whether we should mark the message as saved. - */ -int -mail_copy0 (int argc, char **argv, int mark) +struct append_stat { - mu_message_t msg; - mu_mailbox_t mbx; - char *filename = NULL; - msgset_t *msglist = NULL, *mp; - int sender = 0; - size_t total_size = 0, total_lines = 0, size; - int status; - - if (mu_isupper (argv[0][0])) - sender = 1; - else if (argc >= 2) - filename = mail_expand_name (argv[--argc]); - else - filename = mu_strdup ("mbox"); - - if (msgset_parse (argc, argv, MSG_NODELETED|MSG_SILENT, &msglist)) - { - if (filename) - free (filename); - return 1; - } - - if (sender) - filename = util_outfolder_name (util_get_sender (msglist->msg_part[0], 1)); - - if (!filename) - { - msgset_free (msglist); - return 1; - } + size_t size; + size_t lines; +}; +static int +append_to_mailbox (char const *filename, msgset_t *msglist, int mark, + struct append_stat *totals) +{ + int status; + mu_mailbox_t mbx; + msgset_t *mp; + size_t size; + mu_message_t msg; + if ((status = mu_mailbox_create_default (&mbx, filename)) != 0) { mu_error (_("Cannot create mailbox %s: %s"), filename, mu_strerror (status)); - free (filename); - msgset_free (msglist); return 1; } if ((status = mu_mailbox_open (mbx, MU_STREAM_WRITE | MU_STREAM_CREAT)) != 0) { mu_error (_("Cannot open mailbox %s: %s"), filename, mu_strerror (status)); - free (filename); - msgset_free (msglist); + mu_mailbox_destroy (&mbx); return 1; } @@ -93,9 +68,9 @@ mail_copy0 (int argc, char **argv, int mark) } mu_message_size (msg, &size); - total_size += size; + totals->size += size; mu_message_lines (msg, &size); - total_lines += size; + totals->lines += size; if (mark) { @@ -104,13 +79,179 @@ mail_copy0 (int argc, char **argv, int mark) mu_attribute_set_userflag (attr, MAIL_ATTRIBUTE_SAVED); } } + + mu_mailbox_close (mbx); + mu_mailbox_destroy (&mbx); + return 0; +} + +static int +append_to_file (char const *filename, msgset_t *msglist, int mark, + struct append_stat *totals) +{ + int status; + msgset_t *mp; + mu_stream_t ostr, mstr; + mu_off_t size; + size_t lines; + mu_message_t msg; + mu_locker_t locker; + + status = mu_file_stream_create (&ostr, filename, + MU_STREAM_CREAT|MU_STREAM_APPEND); + if (status) + { + mu_error (_("Cannot open output file %s: %s"), + filename, mu_strerror (status)); + return 1; + } + + status = mu_locker_create (&locker, filename, + MU_LOCKER_KERNEL|MU_LOCKER_RETRY); + if (status) + { + mu_error (_("Cannot create locker %s: %s"), + filename, mu_strerror (status)); + mu_stream_unref (ostr); + return 1; + } + mu_locker_lock_mode (locker, mu_lck_exc); + + status = mu_locker_lock (locker); + if (status) + { + mu_error (_("Cannot lock %s: %s"), + filename, mu_strerror (status)); + mu_locker_destroy (&locker); + mu_stream_unref (ostr); + return 1; + } + + for (mp = msglist; mp; mp = mp->next) + { + mu_envelope_t env; + const char *s, *d; + int n; + + status = util_get_message (mbox, mp->msg_part[0], &msg); + if (status) + break; + status = mu_message_get_envelope (msg, &env); + if (status) + { + mu_error (_("Cannot get envelope: %s"), mu_strerror (status)); + break; + } + + status = mu_envelope_sget_sender (env, &s); + if (status) + { + mu_error (_("Cannot get envelope sender: %s"), mu_strerror (status)); + break; + } + + status = mu_envelope_sget_date (env, &d); + if (status) + { + mu_error (_("Cannot get envelope date: %s"), mu_strerror (status)); + break; + } + + status = mu_stream_printf (ostr, "From %s %s\n%n", s, d, &n); + if (status) + { + mu_error (_("Write error: %s"), mu_strerror (status)); + break; + } + + totals->lines++; + totals->size += n; + + status = mu_message_get_streamref (msg, &mstr); + if (status) + { + mu_error (_("Cannot get message: %s"), mu_strerror (status)); + break; + } + + status = mu_stream_copy (ostr, mstr, 0, &size); + if (status) + { + mu_error (_("Cannot append message: %s"), mu_strerror (status)); + break; + } + + mu_stream_unref (mstr); + + mu_stream_write (ostr, "\n", 1, NULL); + + totals->size += size + 1; + mu_message_lines (msg, &lines); + totals->lines += lines + 1; + + if (mark) + { + mu_attribute_t attr; + mu_message_get_attribute (msg, &attr); + mu_attribute_set_userflag (attr, MAIL_ATTRIBUTE_SAVED); + } + } + + mu_stream_close (ostr); + mu_stream_unref (ostr); + + mu_locker_unlock (locker); + mu_locker_destroy (&locker); + + return 0; +} + +/* + * mail_copy0() is shared between mail_copy() and mail_save(). + * argc, argv -- argument count & vector + * mark -- whether we should mark the message as saved. + */ +int +mail_copy0 (int argc, char **argv, int mark) +{ + char *filename = NULL; + msgset_t *msglist = NULL; + int sender = 0; + struct append_stat totals = { 0, 0 }; + int status; + + if (mu_isupper (argv[0][0])) + sender = 1; + else if (argc >= 2) + filename = mail_expand_name (argv[--argc]); + else + filename = mu_strdup ("mbox"); + + if (msgset_parse (argc, argv, MSG_NODELETED|MSG_SILENT, &msglist)) + { + if (filename) + free (filename); + return 1; + } + + if (sender) + filename = util_outfolder_name (util_get_sender (msglist->msg_part[0], 1)); + + if (!filename) + { + msgset_free (msglist); + return 1; + } + + if (mu_is_proto (filename)) + status = append_to_mailbox (filename, msglist, mark, &totals); + else + status = append_to_file (filename, msglist, mark, &totals); + if (status == 0) mu_printf ("\"%s\" %3lu/%-5lu\n", filename, - (unsigned long) total_lines, (unsigned long) total_size); - - mu_mailbox_close (mbx); - mu_mailbox_destroy (&mbx); + (unsigned long) totals.lines, (unsigned long) totals.size); free (filename); msgset_free (msglist); diff --git a/mail/testsuite/mail/write.exp b/mail/testsuite/mail/write.exp index 68923cf..92447a0 100644 --- a/mail/testsuite/mail/write.exp +++ b/mail/testsuite/mail/write.exp @@ -66,7 +66,7 @@ mail_test "headers" \ # Save messages to the third mailbox mail_command "set folder=\"$MU_FOLDER_DIR\"" mail_test "save 1 2 +three" \ - "\"$MU_FOLDER_DIR/three\" 28/968" + "\"$MU_FOLDER_DIR/three\" 32/1067" mail_test "headers" \ ">* 1 Sergey Poznyakoff Tue Jul 16 12:11 12/390 MBOX"\ @@ -84,7 +84,7 @@ mail_test "headers" \ # Test uppercase commands (Save and Copy) mail_command "set outfolder=\"$MU_FOLDER_DIR\"" mail_test "Save" \ - "\"$MU_FOLDER_DIR/gray\" 12/390" + "\"$MU_FOLDER_DIR/gray\" 14/438" mail_test "file \"$MU_FOLDER_DIR/gray\"" \ "Held 2 messages in $MU_FOLDER_DIR/three" hooks/post-receive -- GNU Mailutils _______________________________________________ Commit-mailutils mailing list Commit-mailutils@gnu.org https://lists.gnu.org/mailman/listinfo/commit-mailutils