.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32 .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. | will give a .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' .\" expand to `' in nroff, nothing in troff, for use with C<>. .tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "ACTIVITYMAIL 1" .TH ACTIVITYMAIL 1 "2008-01-01" "perl v5.8.8" "User Contributed Perl Documentation" .SH "NAME" activitymail \- CVS activity notification .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& # In commitinfo: \& DEFAULT $CVSROOT/CVSROOT/activitymail -l .Ve .PP .Vb 2 \& # In loginfo: \& DEFAULT $CVSROOT/CVSROOT/activitymail -dacf '%{sVv}' -t admins@example.com .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This program may be used for sending email messages for \s-1CVS\s0 repository activity. There are a number of different modes supported. It can send messages for every change to the repository (like \f(CW\*(C`syncmail\*(C'\fR), or it can be used to send a single message for each commit. In the latter case, a list of all the files affected by the commit will be assembled and listed in the single message. This is similar to how \f(CW\*(C`commit_prep\*(C'\fR and \f(CW\*(C`log_accum\*(C'\fR work, but is more efficient. .PP An additional option allows for diffs to be calculated for the recent changes, and either appended to the message (like \f(CW\*(C`syncmail\*(C'\fR does) or added as an attachment (neater). See the \f(CW\*(C`\-d\*(C'\fR and \f(CW\*(C`\-a\*(C'\fR options below. .SH "PREREQUISITES" .IX Header "PREREQUISITES" This script requires Getopt::Std and File::Basename. It also requires a \s-1CVS\s0 server and the \&\fIdiff\fR package. See \*(L"Known Issues\*(R" for more information. .SH "COREQUISITES" .IX Header "COREQUISITES" This script works best with File::Spec installed. See \*(L"Known Issues\*(R" for more information. .SH "USAGE" .IX Header "USAGE" To use this program, you need to check out your \fI\s-1CVSROOT\s0\fR repository from \s-1CVS\s0 and edit some files. Here are the steps to follow: .IP "1." 4 Copy \fIactivitymail\fR into your \fI\s-1CVSROOT\s0\fR checkout. .IP "2." 4 Add \fIactivitymail\fR to the \fI\s-1CVSROOT\s0\fR repository. .IP "3." 4 Add \fIactivitymail\fR to the \fIcheckoutlist\fR file. .IP "4." 4 If you plan to use commit mode (see \*(L"Commit Mode\*(R" below), add a call (or calls) to \f(CW\*(C`activitymail\*(C'\fR with the \f(CW\*(C`\-l\*(C'\fR options to the \fIcommitinfo\fR file. Read the \s-1CVS\s0 docs to determine the format for this file, and to decide which repositories for which you want it run. Here's an example: .Sp .Vb 1 \& DEFAULT $CVSROOT/CVSROOT/activitymail -l .Ve .IP "5." 4 Add a call (or calls) to activitymail to the \fIloginfo\fR file. Note that the \&\f(CW\*(C`\-f\*(C'\fR and \f(CW\*(C`\-t\*(C'\fR options are required here, and the \f(CW\*(C`\-P\*(C'\fR option is a good idea for \s-1CVS\s0 1.12 and later. Use the \f(CW\*(C`\-c\*(C'\fR option if you're running commit mode (i.e., you've added a call with \f(CW\*(C`\-l\*(C'\fR to the \fIcommitinfo\fR file \*(-- see \&\*(L"Commit Mode\*(R" below). Here's an example: .Sp .Vb 1 \& DEFAULT $CVSROOT/CVSROOT/activitymail -cP %p -f '%{sVv}' -t admins@example.com .Ve .IP "6." 4 Commit your changes to \s-1CVSROOT\s0. .SH "OPTIONS" .IX Header "OPTIONS" .IP "\-l" 4 .IX Item "-l" Directory logging mode. Use this mode in the \fIcommitinfo\fR file to log the current directory. Best if used with \f(CW\*(C`\-c\*(C'\fR in the \fIloginfo\fR file \*(-- otherwise it's just a waste. .IP "\-c" 4 .IX Item "-c" Commit mode. This mode will aggregate all the actions on a single commit and send a single message. Must have specified \f(CW\*(C`\-l\*(C'\fR in the \fIcommitinfo\fR file. .IP "\-f '%{sVv}'" 4 .IX Item "-f '%{sVv}'" The file spec argument from \s-1CVS\s0. It must be called as \f(CW\*(C`\-f '%{sVv}'\*(C'\fR. Single quotes are recommended, as some shells otherwise seem to have a hard time. Required unless \f(CW\*(C`\-l\*(C'\fR. \s-1CVS\s0 1.12 and later users should also use \f(CW\*(C`\-P %p\*(C'\fR, as \&\f(CW\*(C`\-f %1{SVv}\*(C'\fR will generate deprecation warnings. .IP "\-P" 4 .IX Item "-P" The directory argument from \s-1CVS\s0. This option is only useful for \s-1CVS\s0 1.12 or later, where the command line format should be \f(CW\*(C`\-P %p \-f '%{sVv}'\*(C'\fR. .IP "\-t " 4 .IX Item "-t " The email address or addresses to send notifications to. Required unless \&\f(CW\*(C`\-l\*(C'\fR. .IP "\-e " 4 .IX Item "-e " Location of the \s-1CVS\s0 executable, e.g., \fI/usr/bin/cvs\fR. Defaults to \fIcvs\fR, thus assuming that the cvs executable is in the path. .IP "\-d" 4 .IX Item "-d" Include the diffs for all the files processed. These will be appended to the notification message unless the \-a option has been specified. .IP "\-j " 4 .IX Item "-j " Location of the diff executable, e.g., \fI/usr/bin/diff\fR. Defaults to \fIdiff\fR, thus assuming that the cvs executable is in the path. Used only for comparing added and deleted files to \fI/dev/null\fR. .IP "\-N " 4 .IX Item "-N " Location of the null file. Defaults to \fI/dev/null\fR. This file will be used to diff against deleted and added files. In most cases this option can be left to the default, but Win32 systems, for example, will need to change it to \fI\s-1NUL\s0\fR or some such. .IP "\-o " 4 .IX Item "-o " Options to pass to the \f(CW\*(C`cvs diff\*(C'\fR command. Useful for changing the behavior of the diff command. Be sure to include these options inside quotation marks so that they will be distinguished from the options parsed by activitymail itself. See diff for a list of available options. Defaults to \&\f(CW\*(C`\-u \-\-minimal\*(C'\fR if not specified. .IP "\-a" 4 .IX Item "-a" Attach diffs to the notification message. The diffs for all the files processed will be calculated, and then they will be added to the message as an attachment. .IP "\-r " 4 .IX Item "-r " An optional reply-to address. This address will be added to a Reply-To header in the notification email. .IP "\-n" 4 .IX Item "-n" Ignore \*(L"New directory\*(R" commits. By default, activitymail sends mail when a directory has been added. Use this option to ignore those actions. .IP "\-i" 4 .IX Item "-i" Ignore imports. By default, activitymail sends mail when a files have been imported. Use this option to ignore those actions. .IP "\-m " 4 .IX Item "-m " An optional message to put at the beginning of the email subject. .IP "\-p" 4 .IX Item "-p" Option to add the name of the \s-1CVS\s0 module to the message subject. .IP "\-S" 4 .IX Item "-S" Optional attempt give the file name or lowest common directory name. Used only in commit mode. .IP "\-s " 4 .IX Item "-s " Location of sendmail. If not specified, activitymail will search for sendmail in the following locations: \f(CW\*(C`/usr/lib/sendmail\*(C'\fR. \f(CW\*(C`/usr/sbin/sendmail\*(C'\fR, \&\f(CW\*(C`/usr/ucblib/sendmail\*(C'\fR. If activitymail cannot find sendmail, it'll throw an exception. .IP "\-u " 4 .IX Item "-u " Email address to use in the From header of the commit email message. Typical usage is to use the \s-1CVS\s0 \f(CW$USER\fR variable to specify an address, e.g., \f(CW\*(C`\-u ${USER}@example.com\*(C'\fR. The default behavior is to provide no From header and to let Sendmail do it. .IP "\-g" 4 .IX Item "-g" Groups the collection of \s-1CVS\s0 transactions in a single commit by the \f(CW$USER\fR environment variable. This is most useful when connecting to \s-1CVS\s0 via \&\f(CW\*(C`:pserver:\*(C'\fR, since the usual method of collecting transactions \*(-- by relying on the value returned by \f(CW\*(C`pgrp\*(C'\fR, won't work. Use in both the \fIcommitinfo\fR and loginfo files, or else it won't work at all! .IP "\-M " 4 .IX Item "-M " Max length for email messages, in kilobytes. If an email greater than this size would be sent then an error message is printed to the user's terminal, instead. This option is useful if your repository contains large binary files not prevented from be diffed by \f(CW\*(C`\-B\*(C'\fR, or when adding many files at once. In those cases, failing to use this option may result in broken mail clients. .IP "\-V" 4 .IX Item "-V" Include the old and new revision numbers after each file listed in the email. .IP "\-H" 4 .IX Item "-H" Generate \s-1HTML\s0 emails. The Content-Type header will be set to \*(L"text/html\*(R" and some basic \s-1HTML\s0 formatting tags used for the display of the commit message. .IP "\-C " 4 .IX Item "-C " Character set to be used in the Content-Type header. Defaults to \*(L"\s-1UTF\-8\s0\*(R". If much of the content in your repository is encoded in a character set incompatible with \s-1UTF\-8\s0, then set this option for a more appropriate character set. .IP "\-w " 4 .IX Item "-w " Include links to specified ViewVC or CVSWeb \s-1URL\s0 for the diffs for each file. Most useful with the \f(CW\*(C`\-H\*(C'\fR option. .IP "\-B " 4 .IX Item "-B " Binary file extension list. \f(CW\*(C`activitymail\*(C'\fR does its best to prevent binary files from being diffed by using the Perl \f(CW\*(C`\-B\*(C'\fR operator to check for binary files. However, this approach doesn't catch all binary files. If you find that \&\f(CW\*(C`activitymail\*(C'\fR is diffing binary files, use this option to specify a quoted, space-delimited list of file name extensions on the binary files that you want \&\f(CW\*(C`activitymail\*(C'\fR to skip. .IP "\-I " 4 .IX Item "-I " A quoted, space-delimited list of regular expressions identifying the files to include in the processing of the commit message. Use \f(CW\*(C`\es\*(C'\fR in place of literal spaces. The file name checked by the regular expression will be relative to the \s-1CVS\s0 module root. Cannot be used in combination with \f(CW\*(C`\-E\*(C'\fR. .IP "\-E " 4 .IX Item "-E " A quoted, space-delimited list of regular expressions identifying the files to exclude from the processing of the commit message. Use \f(CW\*(C`\es\*(C'\fR in place of literal spaces. The file name checked by the regular expression will be relative to the \s-1CVS\s0 module root. Cannot be used in combination with \f(CW\*(C`\-I\*(C'\fR. .IP "\-U" 4 .IX Item "-U" Older versions of \s-1CVS\s0 had a bug that prevented them from properly \fIdiff\fRing when they were passed arguments to be passed to \f(CW\*(C`diff\*(C'\fR with spaces in them. Since we use the \f(CW\*(C`\-L\*(C'\fR option to \fIdiff\fR to pass in the complete file name to be put into the diff headers, this can lead to problems. So if you're using an older version of \s-1CVS\s0 that exhibits this problem (prior to 1.12, if I recall correctly), use this option to replace any spaces in file names with underscores before passing them off to \f(CW\*(C`diff\*(C'\fR. .IP "\-q" 4 .IX Item "-q" Quiet mode. Status messages will be suppressed. Debug messages will still be output if \f(CW\*(C`\-D\*(C'\fR is enabled. .IP "\-Q" 4 .IX Item "-Q" Very quiet mode. In addition to the status messages suppressed by \f(CW\*(C`\-q\*(C'\fR, \f(CW\*(C`\-Q\*(C'\fR will also suppress the message output when an email won't be sent because of a size limitation set by \f(CW\*(C`\-m\*(C'\fR. Debug messages will still be output if \f(CW\*(C`\-D\*(C'\fR is enabled. .IP "\-h" 4 .IX Item "-h" Print usage statement. It's a simplified version of this section of the docs, intended to remind the user of all the options. Be sure to read the detailed descriptions here, first. .IP "\-D" 4 .IX Item "-D" Enables debug mode. This will trigger lots of output. All activitymail debug messages will start with the string \*(L"@@@@@@@@ activitymail debug:\*(R" so that they can be spotted easily. .SH "MODES" .IX Header "MODES" .Sh "Standard Mode" .IX Subsection "Standard Mode" In this mode, a notification message will be sent for every directory affected by a single commit to the repository. This could be a lot of messages if you've made a lot of changes, and is thus highly redundant. .PP To use it, all you need to cimply add a call to \f(CW\*(C`activitymail\*(C'\fR to your \&\fIloginfo\fR file with (at minimum) the \f(CW\*(C`\-f\*(C'\fR, \f(CW\*(C`\-P\*(C'\fR (for \s-1CVS\s0 1.12 and later), and \f(CW\*(C`\-t\*(C'\fR options: .PP .Vb 1 \& DEFAULT $CVSROOT/CVSROOT/activitymail -P %p -f '%{sVv}' -t admins@example.com .Ve .PP To mimic the behavior of syncmail, add the \-d option to append diffs: .PP .Vb 1 \& DEFAULT $CVSROOT/CVSROOT/activitymail -dP %p -f '%{sVv}' -t admins@example.com .Ve .Sh "Commit Mode" .IX Subsection "Commit Mode" This mode takes a just a little more work to put in place, but manages your email resources much more efficiently. In this mode, \f(CW\*(C`activitymail\*(C'\fR tracks all the files changed throughout a single commit and sends a single email when all the changes have been made. This is especially useful in circumstances where many files have been changed at once. In standard mode, many messages will be sent, but in commit mode, only one will be sent. .PP An additional advantge of commit mode is that \f(CW\*(C`activitymail\*(C'\fR will construct a custom subject for the notification messages. In standard mode, the subject is simply the contents of the \f(CW\*(C`\-P\*(C'\fR and \f(CW\*(C`\-f\*(C'\fR options. In commit mode, however, \&\f(CW\*(C`activitymail\*(C'\fR will use either the first sentence of the log message, or the maximum number of words that take up less than 72 characters (including the \&\f(CW\*(C`\-m\*(C'\fR and/or \f(CW\*(C`\-p\*(C'\fR options, if specified). This offers an easy way to see what was done during the commit based on the context of the beginning of the actual log message. \s-1CVS\s0 users thus might want to consider making the first sentence of their messages (up to the first period) be a brief summary, and the rest of the message can be a more detailed description of the changes. .PP To use commit mode, you \fBmust\fR place a call to \f(CW\*(C`activitymail\*(C'\fR with the \f(CW\*(C`\-l\*(C'\fR option in your \fIcommitinfo\fR file for every repository package you want to manage in commit mode. Usually, that's everything, so you can just use the line (as long as you have no other lines \*(-- see cvs for more information): .PP .Vb 1 \& DEFAULT $CVSROOT/CVSROOT/activitymail -l .Ve .PP Then, you'll need to add a second call to \f(CW\*(C`activitymail\*(C'\fR to your \fIloginfo\fR file for the same repository packages as in the \fIcommitinfo\fR file's call to \&\f(CW\*(C`activitymail\*(C'\fR. A convenient line for this purpose (even if you have other log filters in place) is the \s-1ALL\s0 line: .PP .Vb 1 \& ALL $CVSROOT/CVSROOT/activitymail -cf '%{sVv}' -t admins@example.com .Ve .PP The \s-1DEFAULT\s0 line will work equally well. Perhaps you want to have mail sent to different addresses for different repository packages. see cvs for more information on the \fIloginfo\fR file syntax. .PP If you'd like to see diffs for the changes for any particular commit, add the \&\f(CW\*(C`\-d\*(C'\fR option. All of the changes to the repository will be recorded in diff format and appended to the end of the message: .PP .Vb 1 \& ALL $CVSROOT/CVSROOT/activitymail -cdf '%{sVv}' -t admins@example.com .Ve .PP Better still, have the diffs added to the message as attachments by adding the \&\-a option. .PP .Vb 1 \& ALL $CVSROOT/CVSROOT/activitymail -cdaf '%{sVv}' -t admins@example.com .Ve .PP Finally, If you commit to \s-1CVS\s0 via \f(CW\*(C`:pserver:\*(C'\fR, you should use the \-g option to get \f(CW\*(C`activitymail\*(C'\fR to properly group all of the \s-1CVS\s0 activity for a commit. By default, \f(CW\*(C`activitymail\*(C'\fR uses the value returned by \f(CW\*(C`pgrp\*(C'\fR to determine what's part of a single commit action and what's another action. However, in \&\f(CW\*(C`:pserver:\*(C'\fR mode, \f(CW\*(C`pgrp\*(C'\fR always returns the same value. The solution is to use the \f(CW$USER\fR environment variable to group the \s-1CVS\s0 activity. The assumption is that a single user will not be doing two separate commits at the same time, so this should work fine. Note that if you use the \-g option, you \&\fBmust\fR use it in both the \fIcommitinfo\fR file: .PP .Vb 1 \& DEFAULT $CVSROOT/CVSROOT/activitymail -lg .Ve .PP And the \fIloginfo\fR file: .PP .Vb 1 \& ALL $CVSROOT/CVSROOT/activitymail -cdagf '%{sVv}' -t admins@example.com .Ve .SH "KNOWN ISSUES" .IX Header "KNOWN ISSUES" .IP "\(bu" 4 This program depends on the presence of several modules that are distributed standard with Perl. They are Getopt::Std, File::Basename, and File::Spec. If either Getopt::Std or File::Basename isn't present, \f(CW\*(C`activitymail\*(C'\fR won't run. If File::Spec isn't installed (not uncommon, since it's a fairly recent addition to Perl \*(-- SourceForge, for example, doesn't have it as of this writing), \&\f(CW\*(C`activitymail\*(C'\fR will assume very simple Unix semantics for creating file names, and will assume that \f(CW\*(C`/tmp\*(C'\fR is the temp directory. .IP "\(bu" 4 The default \f(CW\*(C`diff\*(C'\fR on SunOS 5.9 does not like the \f(CW\*(C`\-L\*(C'\fR option that \&\f(CW\*(C`activitymail\*(C'\fR uses. The workaround is to install \s-1GNU\s0 \f(CW\*(C`diff\*(C'\fR. .SH "TO DO" .IX Header "TO DO" .IP "\(bu" 4 Change the way diffs are aggregated for messages so that we're not loading them all up into memory, but passing them directly to sendmail instead. This should dramatically lower the amount of memory \f(CW\*(C`activitymail\*(C'\fR takes up during a large commit. .SH "BUGS" .IX Header "BUGS" Please send bug reports to or report them via the \s-1CPAN\s0 Request Tracker at . .SH "AUTHOR" .IX Header "AUTHOR" David Wheeler .SH "SEE ALSO" .IX Header "SEE ALSO" .IP "SVN::Notify" 4 .IX Item "SVN::Notify" This is a port of \f(CW\*(C`activitymail\*(C'\fR to subversion. Only it's a \fBlot\fR better. Check it out! .IP "CVSspam" 4 .IX Item "CVSspam" Ruby-powered \s-1CVS\s0 notification. Includes colored \s-1HTML\s0 representations of diffs right in the email. . .IP "syncmail" 4 .IX Item "syncmail" Python-powered \s-1CVS\s0 notification. Sends emails with diffs for every directory in a single commit. Popular on SourceForge. . .IP "commit_prep & log_accum" 4 .IX Item "commit_prep & log_accum" The original Perl 4\-powered \s-1CVS\s0 notification applications. , . .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright (c) 2002\-2005, David Wheeler. All Rights Reserved. .PP This program is free software; you can redistribute it and/or modify it under the same terms as Perl.