SVN-Notify-2.84000755000767000024 012202440667 12743 5ustar00davidstaff000000000000SVN-Notify-2.84/Build.PL000444000767000024 426212202440667 14400 0ustar00davidstaff000000000000use Module::Build; use Config; use strict; my $class = Module::Build->subclass( class => 'My::Builder', code => q{ sub ACTION_code { my $self = shift; $self->SUPER::ACTION_code(@_); # Copy the test scripts and then set the shebang line and make # sure that they're executable. my @scripts; my $to_dir = $self->localize_file_path("t/scripts"); for my $base (qw(testsvnlook testsendmail)) { my $script = "$to_dir/$base"; push @scripts, $self->localize_file_path($script); my $orig = $self->localize_file_path("t/bin/$base"); $self->copy_if_modified( from => $orig, to_dir => $to_dir, flatten => 1, ); } $self->fix_shebang_line(@scripts); $self->make_executable(@scripts); $self->add_to_cleanup($to_dir); } }, ); my $build = $class->new( module_name => 'SVN::Notify', license => 'perl', add_to_cleanup => [qw(t/data/output.txt t/scripts)], script_files => ['bin/svnnotify'], configure_requires => { 'Module::Build' => '0.2701' }, requires => { 'Getopt::Long' => '2.34', 'perl' => 5.006, }, build_requires => { 'Test::More' => '0.17', 'Module::Build' => '0.2701', 'File::Spec' => 0, }, recommends => { 'Pod::Usage' => '1.33', 'HTML::Entities' => 0, 'Net::SMTP::TLS' => 0, 'Test::Pod' => 1.41, 'Test::Pod::Coverage' => 1.06, 'File::Spec' => 0, 'Text::Trac' => '0.10', }, meta_merge => { resources => { homepage => 'http://search.cpan.org/dist/SVN-Notify/', bugtracker => 'http://github.com/theory/svn-notify/issues/', repository => 'http://github.com/theory/svn-notify/', } }, ); $build->create_build_script; SVN-Notify-2.84/Changes000444000767000024 10614712202440667 14444 0ustar00davidstaff000000000000Revision history for Perl extension SVN::Notify 2.84 2013-08-13T14:25:21Z - Added `--smtp-tls` to the output of `man svnnotify`. - Removed `--smtp-authtype` from the output of `man svnnotify`. - Added `--diff-content-type` option. Defaults to "text/plain" for backward compatibility. Patch by Daniel P. Wright. - Renamed `Filter.pm` to `Filter.pod`, since it's just documentation. - Removed the pod tests from the distribution. - Changed the CSS for message `
` blocks to use `white-space:
        pre-line`, so that long lines will be wrapped, but newlines are still
        respected as usual. Thanks to Dave Abrahams for the patch (and the
        persistence).
      - Changed C to allow it to match any path in the
        repository, including files, rather than just directories. Patch from
        mscherer.
      - Fixed error when the first line of the commit message is less than 10
        characters long (issue #2).
      - Fixed the "From" and "To" headers so that they are properly encoded as
        MIME headers (issue #6).
      - Removed the Makefile.PL, which was just passing through to
        Module::Build. That pattern is now deprecated, and Module::Build is
        required for configuration.

2.83  2011-10-29T00:19:07Z
      - Added the `smtp_port` parameter and accompanying `--smtp-port` option.
        Patch from Gustavo Leite de Mendonça Chaves.
      - Switched from Net::SMTP and Net::SMTP_auth to Net::SMTP::TLS, which
        handles TLS and non TLS and auth and non-auth in any combintation.
        Based on patches from Dawood Sangameshwari and Marino Miculan (RT #
        40188).
      - Added `--smtp-tls` option to enable TLS. Based on patch from Marino
        Miculan.
      - Deprecated `--smtp-authtype`, which is now a no-op. Net::SMTP::TLS
        determines the auth type to use by asking the SMTP server.

2.82  2011-06-26T05:12:04
      - Moved the repository to
        [GitHub](https://github.com/theory/svn-notify/). Yes, I'm aware of the
        irony.

2.81  2011-02-19T03:09:43
      - Removed deprecated use of `qw(...)` as parentheses.
      - Fixed test failures due to a change in the opration of MIME-Q
        encoding.

2.80  2010-01-16T04:40:00
      - Fixed the regular expression for detecting JIRA keys. Thanks to David
        Ferguson for the report (RT#51620).
      - Fixed test failure on Perl 5.11.2.
      - Switched to improved URL links with link text in the documentation.

2.79  2009-04-03T00:36:29
      - Removed a superfluous colon from the dashed line under "Ticket Links"
        in the plain-text rendition of the message. Repored by Dirk Olmes.
      - Fixed a bug in the subject handling code where it could truncate a
        subject to very few characters if it has a dot (.) near the beginning.
        Now it skips 10 characters before looking for a dot at which to
        truncate text for the subject. Reported by Martijn van Beers, who
        noticed a comment in the source indicating that it should have been
        this way all along.
      - Fixed a test so that `svn dirs-changed` returns all of the modified
        directories for a given test. This has no effect on the SVN::Notify
        code, but it means that the test behavior is more correct. Rerpoted by
        Martijn van Beers.
      - Fixed a bug in SVN::Notify::SMTP where `printf` wasn't working
        properly, resulting in plain text email bodies with a number instead
        of a ticket link (Bug #43823). Thanks to Dirk Olmes for the report and
        the debugging.
      - Fixed `--revision-url` to recognize revision link that just use "r"
        followed by a number, such as "r1234". Previously, it had to be "rev
        1234" or "revision 1234".

2.78   2008-09-24T04:41:27
      - When searching for an executable to run, SVN::Notify now also looks in
        the "installbin" and "installscript" directories, as specified by the
        Config module. Patch from John Peacock to improve the finding of apps
        on Strawberry Perl.
      - Documented --to-email-map in `svnnotify`. It was already documented in
        SVN::Notify, but I'd forgoten to include it in the command-line
        script. Reported by Grégory Joseph (Bug #22620).
      - Fixed a bug in the test suite where an unexpected exception was thrown
        on platforms where `sendmail` was not available. Reported by David
        Golden via CPAN-Testers.

2.77  2008-07-18T21:24:44
      - Fixed a typo in a Getopt::Long specification string that reveals
        itself only with Getopt::Long 2.3702 (which is a development release).
        Reported by Andreas Koenig via cpan-testers.

2.76  2008-07-17T19:55:09
      - svnnotify will now throw an exception for any invalid options
        passed to it. Suggested by Ben Tilly.
      - SVN::Notify->get_options() is now aware of SVN::Notify::Alternative,
        and when it is used, will load the alternatives so that they can
        properly register their command-line options and have them processed.
        Reported by Ben Tilly.
      - The error thrown when there is no 'to', to_regex_map', or
        'to_email_app' attributes now waits until after the "pre_prepare"
        filter has been run, so that filters have a chance to set one or more
        of those values. Reported by Jeffrey Borlik.
      - Removed redundant option validation from `svnnotify`. Reported by
        Jeffrey Borlik.
      - Fixed the output triggered by the '--help' and '--man' options.
      - Adjusted missing parameter exceptions to call Pod::Usage::pod2usage()
        when things are run by svnnotify.

2.75  2008-05-18T03:38:11
      - Removed the spelling test from the distribution, since it can
        fail on systems without a spell program or using a different locale.
      - All string command-line options are now decoded from whatever encoding
        is specified by the C<--encoding> option, defaulting to UTF-8. All
        string options are thus properly decoded, excepting those that define
        encodings and languages (which should alwyas be ASCII) and those that
        are specified as hashes (if someone runs into that bug, let me know).
        This fix includes all string options specified by subclasses and
        filters. Reported by Matthew Romaine (Bug #35884).

2.74  2008-05-15T03:29:11
      - Updated copyright.
      - Changed the list example in the Trac sample output to use Greeking so
        that the indentation of wrapping lines can be seen in the output.
      - Improved the CSS for lists in the log message output by
        SVN::notify::HTML (and subclasses) so that bullets are properly
        hangling indents.
      - Removed a bit of redundant CSS from SVN::Notify::HTML.
      - Added a spelling test. This has the benefit of reducing the number of
        annoying spelling errors in the documentation.

2.73  2008-05-04T02:02:21
      - Fixed another lame-ass test failure under Perl 5.6.2. Reported by
        David Cantrell via cpan-testers.

2.72  2008-04-29T17:17:29
      - Fixed misdocumentation of the short version of the --set-sender option
        in C: it's -E, not -S. Reported by Larry Shatzer,
        Jr.
      - Fixed encoding issue on Windows. Patch to fix a stupid oversight
        graciously provided by David Golden.
      - Added four new filter callbacks, "pre_prepare", "post_prepare",
        "pre_execute", and "post_execute". These are called at the begining
        and end of the execution of the prepare() and execute() methods.
        Suggestion and initial patch from Larry Shatzer.
      - Reorganized the table listing the types of filters in
        SVN::Notify::Filter so that they are listed in the order in which they
        execute.

2.71  2008-04-17T18:53:27
      - Fixed test failure in t/filter.t when HTML::Entities is not installed.
        Reported by David Cantrell via CPAN-Testers.
      - Bumped version number for recommended module Text::Trac up to 0.10,
        since that version fixes the last of the bugs I found with its HTML
        output.
      - Adjusted the running of filters against log messages in
        SVN::Notify::HTML so that any linkizing (--linkize), revision URL
        parsing (--revision-url), and ticket reference parsing (--ticket-map)
        is run after the content has been filtered. In 2.70, none of those
        things happened if the message was filtered, even though they did if a
        log message was filtered by SVN::Notify (plain text).
      - Added references to SVN::Notify::Filter::Markdown, now on CPAN.
      - Attributes registered by a filter were not being properly registered
        and processing the command-line arguments when the filter was loaded
        by the --filter option to `svnnotify`. Thanks to Larry Shatzer, Jr.
        for the spot!

2.70  2008-02-29T17:03:26
      - See http://justatheory.com/computers/programming/perl/modules/svnnotify-2.70.html
        for an announcement of this release.
      - Fixed issues with character encoding handling, starting from a patch
        submitted by Toshikazu Kinkoh, and with a lot of experimentation and
        testing by Toshikazu, Martin Lindhe, and myself. Hopefully these
        changes will help solve the various encoding problems that continue to
        crop up:
        + Removed --io-layer, which, it seems, never actually worked.
        + Changed --charset to --encoding, although the former is still
          supported for backwards compatibility.
        + Added --svn-encoding, which identifies the encoding in which data
          is stored in SVN. It defaults to the value of --encoding.
        + Added --diff-encoding, which identifies the encoding in which files
          are stored in SVN. This is useful for the case when log messages
          are written in one encoding and files stored in another. Defaults
          to the value of --svn-encoding.
        + The --language option is now used to set the C<$LANG> environment
          variable for the execution of `svnlook` as well as `sendmail`,
          although not `svnlook diff`, which always runs under the "C" locale.
        + Now only setting the $LANG environment variable for the execution of
          `svnlook` and `sendmail` if it is not already set. This allows the
          existing usages such as `LANG=ja_JP svnnotify ...` to keep working.
        + Fixed character encoding when sending messages via SMTP.
      - Added extensive documentation on how to deal with character encodings
        under "Character Encoding Support" in the SVN::Notify docs.
      - Added support for output filtering. This allows users to easily
        modify content before it's output.
      - Added SVN::Notify::Filter, which fully documents the interface for
        filtering (it's really easy!).
      - Added SVN::Notify::Filter:Trac, which parses log messages from the
        Trac wiki syntax to HTML. Useful for use with SVN::Notify::HTML
        and SVN::Notify::HTML::ColorDiff, and as a nice example of filtering.
      - Split up the output of the HTML  section and the  section
        into two methods in SVN::Notify::HTML in order to simplify filtering.
      - The CSS output by SVN::Notify::HTML is now output inside the 
        tags, rather than inside the  tags. This isn't valid, but will
        hopefully it will allow messages to display better in Web mail clients
        such as Gmail.
      - Eliminated locale warnings during tests.
      - Tweaked the CSS emitted by SVN::Notify::HTML to support a lot of HTML
        in the log message, since such formatting can come from the use of
        SVN::Notify::Filter::Trac and, potentially, other output filters.
      - Fixed issue running tests with a Perl other than /usr/bin/perl without
        running `./Build`. If you just did `./Build test`, it could fail with
        a lot of errors, but no more.
      - Fixed use of the SMTP feature under Perl 5.6. Reported by CPAN testers
        David Cantrell and Slaven Rezic.
      - Fixed the formatting and display of the log message when using the
        --wrap-log option with SVN::Notify::HTML.
      - Eliminated a bogus empty paragraph when using the --wrap-log option
        with SVN::Notify::HTML.
      - Fixed the encoding of the subject line so that Unicode characters
        show up properly. Reported by Ian Anderson (Ticket # 24138).
      - Switched from using `crypt` to using a simple random string algorithm
        for generating email part boundaries, since `crypt` was choking on
        multibyte characters from message subjects. Reported by Toshikazu
        Kinkoh.
      - Added a link to SVN::Notify's Subversion repository.

2.67 2008-02-06T20:15:13
      - Fixed bug where a directory with a valid regular expression character
        could be incorrectly truncated. Patch from Wayne Davison.
      - Fixed a bug where a directory name could be truncated too much if
        there are directory names with common roots. Patch from Wayne Davison.
      - Added the "configure_requires" parameter to Build.PL.
      - Fixed SVN::Notify::HTML::ColorDiff so that it respects
        --max-diff-length.
      - The SVN::Notify::HTML --wrap-log option now wraps individual
        paragraphs as identified by blank lines (with optional spaces), rather
        than wrapping the entire message in a single set of paragraph tags.

2.66  2007-06-17T05:08:29
      - Added some examples complements of Matt Doar.
      - Fixed the specification of recipients passed to the SMTP server so
        that comma-separated email addresses are properly split apart.
        Reported by Michael Plump.
      - Fixed a bug with --to-regex-map where certain entries in it could
        be skipped altogether. Reported by John Peacock.

2.65  2007-03-27T07:01:09
      - Another patch from Martijn van Beers, this one generalizing the
        execution of --ticket-map parageters (Ticket # 21633).
      - Added note and link for HookStart for Windows users who run into
        asynchronous execution issues. Reported by Eric Lemes.
      - Added the --wrap-log option to SVN::Notify::HTML. When passed a true
        value, the log message will be put into a `p` tag instead of a `pre`
        tag, thus allowing it to wrap to the width of the mailer window.
        Needless to say, this means that any whitespace formatting in the log
        message itself will be lost. Suggested by Ian Anderson (Ticket
        #24138).
      - Restored checking for "%s" in the JIRA, RT, Butzilla, and GNATS
        URLs. Reported by Matt Doar.
      - Fixed some spelling errors, thanks to Matt Doar.
      - Added note that verbose output goes to STDOUT.
      - Added support for specifying the location of the revision number via
        an "%d" temlate in the --subject-prefix option. Patch from Jerry
        Veldhuis (Ticket #24309).
      - The --max-diff-length option now works properly in HTML output, as
        well. Reported by Rob Moore (Ticket #25070)
      - Added the --to-email-map option as the inverse of --to-regex-map. That
        is, it maps regular expressions to email addresses, rather than the
        other way around.

2.64  2006-09-28T18:39:47
      - Added notes about Net::SMPT and Net::SMTP_auth to the README file.
        Reported by Nacho Barrientos Arias.
      - The regular expresson for RT ticket numbers now also
        case-insensitively matches "RT" in addtion to "Ticket". Suggested by
        Ask Bjørn Hansen.
      - Now skipping all tests in 't/alt.t' if HTML::Entities is not
        installed. Reported by Marshall Roch.
      - Added a new option, '--ticket-map', to map regular expressions
        that match ticket references to the URLs to create links for those
        references. This allows users to specify any number of ticketing
        systems for which to scan for references in the log message.
      - Deprecated '--ticket-regex' and '--ticket-url' in favor of the new
        '--ticket-map' option.
      - Converted the support for explicit ticketing systems (RT, JIRA,
        GnatsWeb, and Bugzilla) to internally use the 'ticket_map' attribute.
        This change eliminates quite a bit of redundant code. Based on a patch
        from Martijn van Beers (Ticket # 21633).
      - Unified the internal ticket system regular expressions so that
        SVN::Notify::HTML can reference and use exactly the same regexen that
        SVN::Notify uses. Inspired by a patch from Martijn van Beers.

2.63  2006-08-02T18:11:36
      - The tests in t/options.t no longer fail when HTML::Entities is not
        installed. Thanks to Ricardo Signes for the spot! Ticket #20267.
      - The email subject is now encoded in the MIME-Q encoding, in compliance
        with RFC 2047. Patch from Éric Cholet.
      - Now properly setting the binmode on file handles in Win32 when
        running under Perl 5.8.
      - Added the --add-header option to add headers to the outgoing email.
        Useful for things like auto-approval for MLMs. Patch (with tests!)
        from Ricardo Signes.
      - Documented the --language option in the svnnotify script.
      - Before executing 'sendmail', SVN::Notify now sets the $LANG
        environment variable with the contents of the language and charset
        options if language is set. Ticket #16050.

2.62  2006-06-30T18:03:21
      - Changed to() accessor to return the first value in the array in scalar
        context, and all of the items as a list in list context. This makes
        its behavior more consistent with versions of SVN::Notify priort to
        2.61.
      - Added strip_cx_regex() accessor. It also returns the first value in
        scalar context, and the full list in list context, for consistency
        with to().

2.61  2006-06-28T23:07:40
      - Removed unused patch file from the distribution. It was temporary, and
        never supposed to be there, anyway.
      - Added an "Errors-To" header to the outgoing email, using the same
        email address as is used for the "From" header.
      - Added the --set-sender option to specify the envelope sender to the
        same value as is used for the From: header when sending via sendmail.
      - The --to option may now be specified multiple times (or passed as an
        array reference to the constructor) to specify multiple recipients.
        This change allows multiple recipients to be used when sending
        notifications via SMTP. Ticket # 20121. Reported by John Colton.

2.60  2006-06-16T22:42:48
      - HTML output now creates a link from a directory name to its place in
        the diff if the type of diff for the directory is a property change.
        Patch from Lamar Goddard.
      - Added --author-url option. Based on a patch from Lamar Goddard.
      - Deprecated --svnweb-url and --viewcvs-url in favor of the new, more
        general --revision-url. Inspired by a patch from Lamar Goddard.
      - Added --diff-switches option. This can be used to specify switches to
        pass through to 'svnlook diff'. Inspired by a patch from Lamar
        Goddard.

2.59  2006-05-11T17:23:12
      - Fixed a few typos, with thanks to Marshall "Eagle Eyes" Roch.
      - Now throw an exception if 'sendmail' is not specified or cannot be
        found and 'smtp' is not specified. Reported by Eric Lemes.
      - Fixed processing of commad-line arguments under Windows. Reported by
        Eric Lemes. This means that SVN::Notify has now been confirmed to
        actually *work* on Windows.
      - An exception will now be thrown if a Net::SMTP object cannot be
        created. Reported by Eric Lemes.
      - Added note for Windows users about setting environment variables
        required by SVN::Notify. Thanks to Eric Lemes 
        for figuring these things out!
      - Added link to Eric Lemes's tutorial for installing Apache, Subversion,
        and SVN::Notify on Windows.

2.58  2006-05-05T20:44:05
      - Improved documentation of '--ticket-regex', since it seemed to confuse
        people using it with SVN::Notify::HTML. Thanks to Dominic Giampaolo
        for the push.
      - SVN::Notify::HTML now allows '--ticket-regex' to capture only one
        string, in which case it will be used both for the link text and for
        the ticket number passed to the '--ticket-url' format string.
      - Added support for SMTP authentication using Net::SMTP_auth. Use the
        '--smtp-user', '--smtp-pass', and '--smtp-authtype' options to take
        advantage of this feature. Patch from Eric Lemes.
      - Specifying '--verbose' two or more times now turns on SMTP debugging.

2.57  2006-04-06T22:36:18
      - Finally ported to Win32. It was actually a simple matter of changing
        how command pipes are created.
      - Added 'smtp' option to enable sending messages to an SMTP server
        rather than to the local 'sendmail' application. This is essential for
        Windows support.
      - Added --io-layer to the usage statement in 'svnnotify'.
      - Fixed single-dash arguments in documentation so that they're all
        documented with a single dash in SVN::Notify.

2.56  2006-04-04T23:16:37
      - Abstracted creation of the diff file handle into the new diff_handle()
        method.
      - Documented use of diff_handle() in the output() method.
      - Added optional second argument to output() to optionally suppress the
        output of the email headers. This argument is used by the new
        Alternative subclass.
      - Added SVN::Notify::Alternative, which allows multiple versions of a
        commit email to be sent, such as text/plain plus HTML. The multiple
        versions are assembled into a single email message using the
        multipart/alternative media type. For those who want HTML messages but
        must support users that can only read plain text or rely on archives
        that ignore HTML messages, this can be very useful. Based on an
        implementation by Jukka Zitting.
      - Fixed use_ok() tests that weren't running at all.
      - Added an extra newline to separate the file list from an inline diff
        in the plain text format where '--with-diff' has been specified.
      - Moved the "multipart/mixed" content-type header generation from
        output_headers() to output_content_type(), not only because this makes
        more sense, but also because it makes attachments behave better when
        using SVN::Notify::Alternative.
      - Documented accessors in SVN::Notify::HTML.

2.55  2006-04-03T23:11:11
      - Added the 'io-layer' option to specify an alternate IO layer. Will be
        most useful for those with repositories containing text in multiple
        encodings, where it should be set to "raw".
      - Fixed the context output in the subject for the '--subject-cx' option
        so that it's smarter about determining the longest common path.
        Reported by Max Horn.
      - No longer modifying the values of the 'to_regex_map' hash, so as not
        to mess with folks who might be passing it as a hash to more than one
        call to new(). Reported by Darby Felton.
      - Added a 'meta http-equiv="content-type"' tag to HTML output that
        includes the character set to help some clients in the proper display
        of the characters in an HTML email. I'm not sure if any clients
        actually need this help, but it certainly can't hurt!
      - Added the '--css-url' option to specify an alternate style sheet for
        HTML emails. SVN::Notify::HTML's own CSS is left in the email, as
        well, so the specified style sheet can just override the default,
        rather than have to style everything itself. Yes, it takes advantage
        of the "cascading" feature of cascading style sheets! Based on a
        suggestion by Steve James.

2.54  2006-03-06T00:33:42
      - Added "/usr/bin" to the list of paths searched for executables.
        Suggested by Nacho Barrientos.
      - Added '--max-diff-length' option. Patch from David Burley/SourceForge.

2.53  2006-02-24T21:30:48
      - Added 'header' and 'footer' attributes and command-line options to
        specify text to be put at the head and foot of each message. For HTML
        messages, the text will be escaped, unless it starts with "<", in
        which case it will be assumed to be valid HTML and will therefore not
        be escaped. Either way, it will be output between 
tags with the IDs "header" or "footer" as appropriate. Based on a patch from David Burley/SourceForge. - Fixed the executable-searching algorithm added in 2.52 to add ".exe" to the name of the executable being searched for if $^O eq 'MSWin32'. - Fixed encoding issues so that, under Perl 5.8 and later, the IO layer is set on file handles so as to encode input and decode output in the character set specified by the 'charset' attribute. CPAN # 16050, reported by Michael Zehrer. - Added a second argument to all calls to encode_entities() in SVN::Notify::HTML and SVN::Notify::HTML::ColorDiff so that only '>'. '<', '&', and '"' are escaped. - Fixed a bug in the _find_exe() function that was attempting to modify a constant variable. Patch from John Peacock. - Turned the _find_exe() function into the find_exe() class method, since subclasses (such as SVN::Notify::Mirror) might want to use it. 2.52 2006-02-19T18:50:24 - Now uses File::Spec->path to search for a validate sendmail or svnlook when they're not specified via their respective command-line options or environment variables. Suggested by Andreas Koenig. Not that they should probably be explicitly set anyway, as the PATH environment variable tends to be non-existent when running under Apache. 2.51 2006-01-02T23:28:11 - Fixed ColorDiff HTML to once again be valid XHTML 1.1. 2.50 2005-11-10T23:27:22 - Added "ticket-url" and "ticket-regex" options to be used by those who want to match ticket identifers for systems other than RT, Bugzilla, GNATS, and JIRA. Based on a patch from Andrew O'Brien. - Removed bogus 'use lib' line put into Makefile.PL by a prerelease version of Module::Build. - Fixed HTML tests to match either "'" or "'", since HTML::Entities can be configured differently on different systems. 2.49 2005-09-29T17:26:14 - Now require Getopt::Long 2.34 so that the --to-regex-map option works correctly when it is used only once on the command-line. 2.48 2005-09-06T19:14:35 - Swiched from and to and elements in SVN::Notify::HTML::ColorDiff in order to make the markup more semantic. 2.47 2005-09-03T18:54:43 - Fixed options tests to work correctly with older versions of Getopt::Long. Reported by Craig McElroy. - Slick new CSS treatment used for the HTML and HTML::ColorDiff emails. Based on a patch from Bill Lynch. - Added "svnweb_url" option. Based on a patch from Ricardo Signes. 2.46 2005-05-05T05:22:54 - Added support for "Copied" files to HTML::ColorDiff so that they display properly. 2.45 2005-05-04T20:38:18 - Added support for links to the GNATS bug tracking system. Patch from Nathan Walp. 2.44 2005-03-18T06:10:01 - Fixed Name in POD so that SVN::Notify's POD gets indexed by search.cpan.org. Reported by Ricardo Signes. 2.43 2004-11-24T18:49:40 - Added "--strip-cx-regex" option to strip out parts of the context from the subject. Useful for removing parts of the file names you might not be interested in seeing in every commit message. - Added "--no-first-line" option to omit the first sentence or line of the log message from the subject. Useful in combination with the "--subject-cx" option. 2.42 2004-11-19T18:47:20 - Changed "Files" to "Paths" in hash returned by "file_label_map()" since directories can be listed as well as files. - Fixed SVN::Notify::HTML so that directories listed among the changed paths are not links. - Requiring Module::Build 0.26 to make sure that the installation works properly. Reported by Robert Spier. 2.41 2004-10-21T20:33:25 - Added missing newline between the commit metadata and the log message in SVN::Notify. 2.40 2004-10-21T19:49:40 - Fixed accessor generation so that accessors created for the attributes passed to "register_attributes()" but a subclass are created in the subclass' package instead of in SVN::Notify. - Changed parsing for JIRA keys to use any set of capital letters followed by a dash and then a number, rather than the literal string "JIRA-" followed by a number. Reported by Garrett Rooney. - Modified the regular expression patterns for the RT, Bugzilla, RT, and ViewCVS links to properly match on word boundaries, so that strings like "humbug 12" don't match. - Modified the ViewCVS link regular expression pattern so that it matches strings like "rev 12" as well as "revision 12". - Modified the RT link regular expression pattern so that it matches strings like "RT-Ticket: 23" as well as "Ticket 1234". Suggested by Jesse Vincent. - Added complicated example to try to show off all of the major features. I will keep this up-to-date going forward in order to post sample output on the Web. - Fixed the parsing of log messages so that empty lines are no longer eliminated. - HTML::ColorDiff now properly handles the listing of binary files in the diff, marking them with a new class, "binary", and using the same CSS as is used for the "propset" class. - In HTML::ColorDiff, Fixed CSS for the "delfile" class to properly wrap it in a border like the other files in the diff. - Added labels to the HTML::ColorDiff diff file sections to indicate the type of change ("Modified", "Added", "Deleted", or "Property changes"). - Moved the "rt_url", "bugzilla_url", and "jira_url" parameters from SVN::Notify::HTML to SVN::Notify, where they are used to add URLs to the text version of log messages. 2.30 2004-10-19T05:20:02 - Added "register_attributes()" class method so that subclasses can easily specify their own attributes and the corresponding command- line options. This method will also create accessors for such attributes. - Moved the command-line option parsing to the new "get_options()" class method, so options specified via the "register_attributes()" class method can centrally be parsed from the command-line. - Removed the deprecated "format" option and parameter to new(). - Added the "language" attribute to specify the language of the message, file names, and file contents. - Added the "linkize" attribute to SVN::Notify::HTML. When this attribute is set to a true value, URLs and email addresses in the log message will be turned into links. - Added new "bugzilla_url", "jira_url", and "rt_url" attributes to SVN::Notify. If present, these URLs will be used to create links from certain strings in the log message. - Changed the "viewcvs_url" attribute to require an "%s" format for the placement of the revision number to match the way the new URL attributes work. As an interim measure, SVN::Notify will append what it has always appended and emit a warning if there is no "%s" in the "viewcvs_url" string. - Fixed SVN::Notify::HTML::ColorDiff so that it does not output two separate sections for a single file that was both modified (or added or deleted) and had properties set. 2.22 2004-10-15T06:12:46 - Fixed diff parsing in SVN::Notitfy::HTML and SVN::Notitfy::HTML::ColoDiff to recognize added and deleted files. - Added links to files for which properties were set down into their place in the diff in SVN::Notitfy::HTML and SVN::Notitfy::HTML::ColoDiff. - Changed the class for each file in the diff output by SVN::Notitfy::HTML::ColoDiff to be specific to whether the file was modified, added, deleted, or just had its properties set. 2.21 2004-10-09T22:37:34 - Tweaked HTML to make it all XHTML 1.1 compliant. - Switched to using attribute accessors instead of direct hash access in the subclasses to serve as a better example for others. - Changed the diff output methods to accept the diff input file handle as the second argument, so that it is created in only one place. 2.20 2004-10-09T20:01:28 - Subclassing Module::Build in Build.PL to move and set the shebang line in test scripts during "./Build" instead of simply changing the shebang line in-place during "perl Build.PL". - Split the "start_message()" method into two methods, the second one called "output_metadata()", to separate starting the message and outputting content. - Added "output_css()" method to SVN::Notify::HTML, called by its "start_message()" method to output CSS for the HTML email. - Added CSS to the email in SVN::Notify::HTML. - Added links from the changed file list in HTML email to the included diff. - Added SVN::Notify::HTML::ColorDiff, a new subclass that colorizes the diff when it is included in the HTML email message. 2.10 2004-10-07T06:18:59 - Added many new methods to break up the various activities of assembling a notification message. This will make subclassing easier. - Moved all HTML notification functionality into a new subclass, SVN::Notify::HTML. - Added new "handler" parameter to new() and "--handler" option to svnnotify to specify what subclass should handle sending the notification. Just specify the name of a subclass, such as "HTML" for SVN::Notify::HTML. This replaces the "format" parameter, which is now deprecated. - Added code to Build.PL to set the shebang line in the test scripts. Reported by Robert Spier. - Changed name of attached diff file to be named for the revision and the committer, rather than the committer and the date. Suggested by Robert Spier. - Added Author, Date, and Revision information to the top of each message. - The ViewCVS URL is no longer output for each file. A single link for the entire revision number is put at the top of the email, instead. ViewCVS Revision URL syntax pointed out by Peter Valdemar Morch. - Changed the C method to C to better reflect its generalized use as the method that executes actions in response to Subversion activity. - The tests no longer require HTML::Entities to run. The HTML email tests will be skipped if it is not installed. - Added accessor methods for the attributes of SVN::Notify. 2.00 2004-10-04T05:09:17 - First release, ported from activitymail 1.11, but completely rewritten, with a new script interface and a separate class that manages everything. - Added "to_cx_regex" parameter to control the recipients based on how regular expressions match directory names. - Added "charset" parameter. - Added "user_domain" parameter. - Added "sendmail" parameter.SVN-Notify-2.84/MANIFEST000444000767000024 165012202440667 14233 0ustar00davidstaff000000000000bin/svnnotify Build.PL Changes lib/SVN/Notify.pm lib/SVN/Notify/Alternative.pm lib/SVN/Notify/Filter.pod lib/SVN/Notify/Filter/Trac.pm lib/SVN/Notify/HTML.pm lib/SVN/Notify/HTML/ColorDiff.pm MANIFEST This list of files META.json META.yml README.md t/alt.t t/base.t t/bin/testsendmail t/bin/testsendmail.bat t/bin/testsvnlook t/bin/testsvnlook.bat t/data/changed/111.txt t/data/changed/222.txt t/data/changed/333.txt t/data/changed/444.txt t/data/changed/555.txt t/data/diff-noadd/111.txt t/data/diff/111.txt t/data/diff/333.txt t/data/diff/444.txt t/data/diff/555.txt t/data/dirs-changed/111.txt t/data/dirs-changed/222.txt t/data/dirs-changed/333.txt t/data/dirs-changed/444.txt t/data/dirs-changed/555.txt t/data/info/111.txt t/data/info/222.txt t/data/info/333.txt t/data/info/444.txt t/data/info/555.txt t/errors.t t/filter.t t/html.t t/htmlcolordiff.t t/options.t t/script.t t/scripts/testsendmail t/scripts/testsvnlook t/smtp.t SVN-Notify-2.84/META.json000444000767000024 430412202440667 14522 0ustar00davidstaff000000000000{ "abstract" : "Subversion activity notification", "author" : [ "David E. Wheeler " ], "dynamic_config" : 1, "generated_by" : "Module::Build version 0.4005, CPAN::Meta::Converter version 2.120921", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "SVN-Notify", "prereqs" : { "build" : { "requires" : { "File::Spec" : "0", "Module::Build" : "0.2701", "Test::More" : "0.17" } }, "configure" : { "requires" : { "Module::Build" : "0.2701" } }, "runtime" : { "recommends" : { "File::Spec" : "0", "HTML::Entities" : "0", "Net::SMTP::TLS" : "0", "Pod::Usage" : "1.33", "Test::Pod" : "1.41", "Test::Pod::Coverage" : "1.06", "Text::Trac" : "0.10" }, "requires" : { "Getopt::Long" : "2.34", "perl" : "5.006" } } }, "provides" : { "SVN::Notify" : { "file" : "lib/SVN/Notify.pm", "version" : "2.84" }, "SVN::Notify::Alternative" : { "file" : "lib/SVN/Notify/Alternative.pm", "version" : "1.0" }, "SVN::Notify::Filter::Trac" : { "file" : "lib/SVN/Notify/Filter/Trac.pm", "version" : "2.84" }, "SVN::Notify::HTML" : { "file" : "lib/SVN/Notify/HTML.pm", "version" : "2.84" }, "SVN::Notify::HTML::ColorDiff" : { "file" : "lib/SVN/Notify/HTML/ColorDiff.pm", "version" : "2.84" }, "SVN::Notify::SMTP" : { "file" : "lib/SVN/Notify.pm", "version" : 0 } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "http://github.com/theory/svn-notify/issues/" }, "homepage" : "http://search.cpan.org/dist/SVN-Notify/", "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "url" : "http://github.com/theory/svn-notify/" } }, "version" : "2.84" } SVN-Notify-2.84/META.yml000444000767000024 247612202440667 14362 0ustar00davidstaff000000000000--- abstract: 'Subversion activity notification' author: - 'David E. Wheeler ' build_requires: File::Spec: 0 Module::Build: 0.2701 Test::More: 0.17 configure_requires: Module::Build: 0.2701 dynamic_config: 1 generated_by: 'Module::Build version 0.4005, CPAN::Meta::Converter version 2.120921' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: SVN-Notify provides: SVN::Notify: file: lib/SVN/Notify.pm version: 2.84 SVN::Notify::Alternative: file: lib/SVN/Notify/Alternative.pm version: 1.0 SVN::Notify::Filter::Trac: file: lib/SVN/Notify/Filter/Trac.pm version: 2.84 SVN::Notify::HTML: file: lib/SVN/Notify/HTML.pm version: 2.84 SVN::Notify::HTML::ColorDiff: file: lib/SVN/Notify/HTML/ColorDiff.pm version: 2.84 SVN::Notify::SMTP: file: lib/SVN/Notify.pm version: 0 recommends: File::Spec: 0 HTML::Entities: 0 Net::SMTP::TLS: 0 Pod::Usage: 1.33 Test::Pod: 1.41 Test::Pod::Coverage: 1.06 Text::Trac: 0.10 requires: Getopt::Long: 2.34 perl: 5.006 resources: bugtracker: http://github.com/theory/svn-notify/issues/ homepage: http://search.cpan.org/dist/SVN-Notify/ license: http://dev.perl.org/licenses/ repository: http://github.com/theory/svn-notify/ version: 2.84 SVN-Notify-2.84/README.md000444000767000024 356412202440667 14367 0ustar00davidstaff000000000000SVN/Notify version 2.84 ======================= This class may be used for sending email messages for [Subversion](http://subversion.tigris.org/) repository activity. There are a number of different modes supported, and SVN::Notify is fully subclassable, to easily add new functionality. By default, a list of all the files affected by the commit will be assembled and listed in a single message. An additional option allows diffs to be calculated for the changes and either appended to the message or added as an attachment. The included subclass, SVN::Notify::HTML, allows the messages to be sent in HTML format. Installation ------------ To install this module, type the following: perl Build.PL ./Build ./Build test ./Build install Or, if you don't have Module::Build installed, type the following: perl Makefile.PL make make test make install Dependencies ------------ SVN::Notify has the following dependencies: * Getopt::Long This module is included with Perl. * Pod::Usage For calling 'svnnotify' with the --help or --man options, or when it fails to process the command-line options, usage output will be triggered by Pod::Usage, has been included with Perl since 5.6.0. * HTML::Entities This module is required for sending HTML-formatted notifications with SVN::Notify::HTML. * Net::SMTP This module is required for sending notification messages via SMTP rather than by sendmail (e.g., under Windows). That is, it is required when using the --smtp option. * Net::SMTP_auth This module is required for sending notifications messages via an authenticating SMTP server, i.e., when using the --smtp-authtype option. Copyright and License --------------------- Copyright (c) 2004-2011 David E. Wheeler. Some Rights Reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. SVN-Notify-2.84/bin000755000767000024 012202440667 13513 5ustar00davidstaff000000000000SVN-Notify-2.84/bin/svnnotify000555000767000024 1310512202440667 15655 0ustar00davidstaff000000000000#!/usr/bin/perl -w use strict; use SVN::Notify; # Parse out the options. my $opts = SVN::Notify->get_options or require Pod::Usage && Pod::Usage::pod2usage(2); # Handle version, help, man. if (delete $opts->{version}) { print 'svnnotify ', SVN::Notify->VERSION, $/; exit; } require Pod::Usage && Pod::Usage::pod2usage( '-verbose' => 99, '-sections' => '(?i:(Usage|Options))', '-exitval' => 0, ) if delete $opts->{help}; require Pod::Usage && Pod::Usage::pod2usage( '-verbose' => 99, '-sections' => '.+', '-exitval' => 0, ) if delete $opts->{man}; # What class are we using? my $class = 'SVN::Notify'; $class .= '::' . delete $opts->{handler} if $opts->{handler}; # Do it! my $notifier = $class->new(%$opts); $notifier->prepare; $notifier->execute; 1; __END__ =head1 Name svnnotify - Subversion activity notification =head1 Usage svnnotify --repos-path "$1" --revision "$2" [options] =head1 Options -p --repos-path PATH Path to the Subversion repository. Required. -r --revision REVISION Commit revision number. Required. -t --to ADDRESS The notification destination email address. Required unless --to-regex-map. -x --to-regex-map TO=REGEX A mapping between a destination email address and a regular expression to match against the directories affected by the commit. Required unless --to or --to-email-map. --to-email-map REGEX=TO The inverse of --to-regex-map: Map a regular expresion to an email address. Required unless --to or --to-regex-map. -f --from ADDRESS Email address to use in the From header. -D --user-domain DOMAIN Domain name to append to the username to complete the email address in the From header. -l --svnlook SVNLOOK Location of the svnlook executable. -s --sendmail SENDMAIL Location of the sendmail executable. -E --set-sender Set the envelope sender to the from address. --smtp ADDRESS Address for an SMTP server. --smtp-user USERNAME Username for authenticating to a SMTP server. --smtp-pass PASSWORD Password for authenticating to a SMTP server. --smtp-port PORT Port to connect to on the SMTP server. --smtp-tls Enable TLS/SSL connection to the SMTP server. -c --encoding ENCODING The character encoding for reading and writing data. --svn-encoding ENCODING The character encoding of the log message and the repository files. --diff-encoding ENCODING The character encoding of the repository files. -g --language LANGUAGE Value for the Content-Language header and $LANG environment variable. -d --with-diff Include the diff in the message. -a --attach-diff Attach the diff to the message. -w --diff-switches SWITCHES Switches to pass to C. --diff-content-type TYPE Sets the Content-Type for diff attachments. -R --reply-to ADDRESS Address for use in the Reply-To header. --add-header NAME=VALUE Add an extra header to the email. -P --subject-prefix PREFIX String to prepend to the subject. -C --subject-cx Include the context of the commit in the subject. -X --strip-cx-regex Regex to remove part of the CX file name from the subject. -O --no-first-line Do not include the first line of the log message in the subject. -i --max-sub-length LENGTH Maximum size of the subject line. -e --max-diff-length LENGTH Maximum size of the diff output. -H --handler HANDLER The notification handler, such as "HTML". -F --filter FILTER An output filter, such as "Markdown". -A --author-url URL Include link to specified author URL. -U --revision-url URL Include links to specified Revision URL. -T --rt-url URL Include links to specified Request Tracker URL. -B --bugzilla-url URL Include links to specified Bugzilla URL. -J --jira-url URL Include links to specified JIRA URL. -G --gnats-url URL Include links to specified Gnats URL. --ticket-map REGEX=URL Regex and URL for custom ticket identifiers. --header HEADER Text header to display before body. --footer FOOTER Text footer to display at end of body. -V --verbose Incremental verbose mode. -h --help Print this usage statement and exit. -m --man Print the complete documentation and exit. -v --version Print the version number and exit. More options may be supported by the subclass of SVN::Notify specified by the C<--handler> option or by filters specified by the C<--filter> option. Consult the documentation of the relevant modules for details. =head1 See Also See L for the complete documentation. If you're having issues with character encodings, see especially the L section. =head1 Author David E. Wheeler =head1 Copyright and License Copyright (c) 2004-2011 David E. Wheeler. Some Rights Reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut SVN-Notify-2.84/lib000755000767000024 012202440667 13511 5ustar00davidstaff000000000000SVN-Notify-2.84/lib/SVN000755000767000024 012202440667 14157 5ustar00davidstaff000000000000SVN-Notify-2.84/lib/SVN/Notify.pm000444000767000024 24602512202440667 16173 0ustar00davidstaff000000000000package SVN::Notify; use strict; require 5.006_000; use constant WIN32 => $^O eq 'MSWin32'; use constant PERL58 => $] > 5.007_000; require Encode if PERL58; $SVN::Notify::VERSION = '2.84'; # Make sure any output (such as from _dbpnt()) triggers no Perl warnings. if (PERL58) { # Dupe them? binmode STDOUT, ':utf8'; binmode STDERR, ':utf8'; } =head1 Name SVN::Notify - Subversion activity notification =head1 Synopsis Use F in F: svnnotify --repos-path "$1" --revision "$2" \ --to developers@example.com [options] svnnotify --repos-path "$1" --revision "$2" \ --to-cx-regex i10n@example.com=I10N [options] Use the class in a custom script: use SVN::Notify; my $notifier = SVN::Notify->new(%params); $notifier->prepare; $notifier->execute; =head1 Description This class may be used for sending email messages for Subversion repository activity. There are a number of different modes supported, and SVN::Notify is fully subclassable, to add new functionality, and offers L to easily modify the format of its messages. By default, A list of all the files affected by the commit will be assembled and listed in a single message. An additional option allows diffs to be calculated for the changes and either appended to the message or added as an attachment. See the C and C options below. =head1 Usage To use SVN::Notify, simply add a call to F to your Subversion repository's F script. This script lives in the F directory at the root of the repository directory; consult the documentation in F for details. Make sure that you specify the complete path to F, as well as to F and F in the options passed to F so that everything executes properly. And if you specify any string options, be sure that they are in the encoding specified by the C<--encoding> option, or UTF-8 if you have not specified C<--encoding>. =head2 Windows Usage To get SVN::Notify to work properly in a F script, you must set the following environment variables, as they will likely not be present inside Apache: =over =item PATH=C:\perl\bin =item OS=Windows_NT =item SystemRoot=C:\WINDOWS =back See L for more detailed information on getting SVN::Notify running on Windows. If you have issues with asynchronous execution, try using L|http://www.koders.com/csharp/fidE2724F44EF2D47F1C0FE76C538006435FA20051D.aspx> to run F. =cut # Map the svnlook changed codes to nice labels. my %map = ( U => 'Modified Paths', A => 'Added Paths', D => 'Removed Paths', _ => 'Property Changed', ); my %filters; ############################################################################## =head1 Class Interface =head2 Constructor =head3 new my $notifier = SVN::Notify->new(%params); Constructs and returns a new SVN::Notify object. This object is a handle on the whole process of collecting meta data and content for the commit email and then sending it. As such, it takes a number of parameters to affect that process. Each of these parameters has a corresponding command-line option that can be passed to F. The options have the same names as these parameters, but any underscores you see here should be replaced with dashes when passed to F. Most also have a corresponding single-character option. On Perl 5.8 and higher, If you pass parameters to C, they B be L if they have any non-ASCII characters. Supported parameters: =over =item repos_path svnnotify --repos-path "$PATH" svnnotify -p "$PATH" The path to the Subversion repository. The path is passed as the first argument when Subversion executes F. So you can simply pass C<$1> to this parameter if you like. See the documentation in F for details. Required. =item revision svnnotify --revision "$REV" svnnotify -r "$REV" The revision number for the current commit. The revision number is passed as the second argument when Subversion executes F. So you can simply pass C<$2> to this parameter if you like. See the documentation in F for details. Required. =item to svnnotify --to commiters@example.com svnnotify -t commiters@example.com --to managers@example.com The address or addresses to which to send the notification email. Can be used multiple times to specify multiple addresses. This parameter is required unless either C or C is specified. =item to_regex_map svnnotify --to-regex-map translate@example.com=L18N \ -x legal@example.com=License This parameter specifies a hash reference of email addresses to regular expression strings. SVN::Notify will compile the regular expression strings into regular expression objects, and then send notification messages if and only if the name of one or more of the paths affected by a commit matches the regular expression. This is a good way to have a notification email sent to a particular mail address (or comma-delimited list of addresses) only for certain parts of the subversion tree. This parameter is required unless C or C is specified. The command-line options, C<--to-regex_map> and C<-x>, can be specified any number of times, once for each entry in the hash to be passed to C. The value passed to the option must be in the form of the key and the value separated by an equal sign. Consult the L documentation for more information. Here's an example complements of Matt Doar of how to use C to do per-branch matching: author=`svnlook author $REPOS -r $REV` # The mail regexes should match all the top-level directories /usr/bin/svnnotify --repos-path "$REPOS" --revision "$REV" \ -x eng-bar@example.com,${EXTRAS}="^Bar" \ -x eng-foo@example.com,${EXTRAS}="^trunk/Foo|^branches/Foo|^tags/Foo" \ -x $author@example.com="^users" --subject-cx =item to_email_map svnnotify --to-email-map L18N=translate@example.com \ --to-email-map License=legal@example.com The inverse of C: The regular expression is the hash key and the email address or addresses are the value. =item from svnnotify --from somewhere@example.com svnnotify -f elsewhere@example.com The email address to use in the "From" line of the email. If not specified, SVN::Notify will use the username from the commit, as returned by C. =item user_domain svnnotify --user-domain example.com svnnotify -D example.net A domain name to append to the username for the "From" header of the email. During a Subversion commit, the username returned by C is usually something like a Unix login name. SVN::Notify will use this username in the email "From" header unless the C parameter is specified. If you wish to have the username take the form of a real email address, specify a domain name and SVN::Notify will append C<\@$domain_name> to the username in order to create a real email address. This can be useful if all of your committers have an email address that corresponds to their username at the domain specified by the C parameter. =item svnlook svnnotify --svnlook /path/to/svnlook svnnotify -l /path/to/svnlook The location of the F executable. If not specified, SVN::Notify will search through the directories in the C<$PATH> environment variable, plus in F and F, for an F executable. Specify a full path to F via this option or by setting the C<$SVNLOOK> environment variable if F isn't in your path or to avoid loading L. It's important to provide a complete path to F because the environment during the execution of F is anemic, with nary a C<$PATH> environment variable to be found. So if F appears not to be working at all (and Subversion seems loathe to log when it dies!), make sure that you have specified the complete path to a working F executable. =item sendmail svnnotify --sendmail /path/to/sendmail svnnotify -s /path/to/sendmail The location of the F executable. If neither the C nor the C parameter is specified, SVN::Notify will search through the directories in the C<$PATH> environment variable, plus in F and F, for an F executable. Specify a full path to F via this option or by setting the C<$SENDMAIL> environment variable if F isn't in your path or to avoid loading L. The same caveats as applied to the location of the F executable apply here. =item set_sender svnnotify --set-sender svnnotify -E Uses the C<-f> option to C to set the envelope sender address of the email to the same address as is used for the "From" header. If you're also using the C option, be sure to make it B an email address. Don't include any other junk in it, like a sender's name. Ignored when using C. =item smtp svnnotify --smtp smtp.example.com The address for an SMTP server through which to send the notification email. If unspecified, SVN::Notify will use F to send the message. If F is not installed locally (such as on Windows boxes!), you I specify an SMTP server. =item smtp_tls svnnotify --smtp-tls Use TLS authentication and encrypted channels for connecting with the server. Usually, TLS servers will require user/password authentication. =item smtp_user svnnotify --smtp-user myuser The user name for SMTP authentication. If this option is specified, SVN::Notify will use L to send the notification message, and will of course authenticate to the SMTP server. =item smtp_pass svnnotify --smtp-pass mypassword The password for SMTP authentication. Use in parallel with C. =item smtp_port svnnotify --smtp-port 465 The port for an SMTP server through which to send the notification email. The default port is 25. =item smtp_authtype svnnotify --smtp-authtype authtype Deprecated in SVN::Notify 2.83, where it has become a no-op. The auth type is determined by the contents returned by the SMTP server's response to the C command. See L for details. =item encoding svnnotify --encoding UTF-8 svnnotify -c Big5 The character set typically used on the repository for log messages, file names, and file contents. Used to specify the character set in the email Content-Type headers and, when the C parameter is specified, the C<$LANG> environment variable when launching C. See L for more information. Defaults to "UTF-8". =item charset svnnotify --charset UTF-8 Deprecated. Use C instead. =item svn_encoding svnnotify --svn-encoding euc-jp The character set used in files and log messages managed in Subversion. It's useful to set this option if you store files in Subversion using one character set but want to send notification messages in a different character set. Therefore C would be used for the notification message, and C would be used to read in data from Subversion. See L for more information. Defaults to the value stored in C. =item diff_encoding svnnotify --diff-encoding iso-2022-jp The character set used by files in Subversion, and thus present in the the diff. It's useful to set this option if you store files in Subversion using one character write log messages in a different character set. Therefore C would be used to read the log message and C would be used to read the diff from Subversion. See L for more information. Defaults to the value stored in C. =item language svnnotify --language fr svnnotify -g i-klingon The language typically used on the repository for log messages, file names, and file contents. Used to specify the email Content-Language header and to set the C<$LANG> environment variable to C<< $notify->language . '.' . $notify->encoding >> before executing C and C (but not for sending data to Net::SMTP). Undefined by default, meaning that no Content-Language header is output and the C<$LANG> environment variable will not be set. See L for more information. =item with_diff svnnotify --with-diff svnnotify -d A boolean value specifying whether or not to include the output of C in the notification email. The diff will be inline at the end of the email unless the C parameter specifies a true value. =item attach_diff svnnotify --attach-diff svnnotify -a A boolean value specifying whether or not to attach the output of C to the notification email. Rather than being inline in the body of the email, this parameter causes SVN::Notify to attach the diff as a separate file, named for the user who triggered the commit and the date and time UTC at which the commit took place. Specifying this parameter to a true value implicitly sets the C parameter to a true value. =item diff_switches svnnotify --diff-switches '--no-diff-added' svnnotify -w '--no-diff-deleted' Switches to pass to C, such as C<--no-diff-deleted> and C<--no-diff-added>. And who knows, maybe someday it will support the same options as C, such as C<--diff-cmd> and C<--extensions>. Only relevant when used with C or C. =item diff_content_type svnnotify --diff-content-type 'text/x-diff' Sets the Content-Type header for attached diffs. The default, if this parameter is not passed, is 'text/plain'. This parameter has no effect if '--attach-diff' is not specified. =item reply_to svnnotify --reply-to devlist@example.com svnnotify -R developers@example.net The email address to use in the "Reply-To" header of the notification email. No "Reply-To" header will be added to the email if no value is specified for the C parameter. =item add_headers svnnotify --add-header X-Approve=letMeIn Add a header to the notification email message. The header name and its value must be separated by an equals sign. Specify the option multiple times in order to add multiple headers. Headers with the same names are allowed. Not to be confused with the C<--header> option, which adds introductory text to the beginning of the email body. =item subject_prefix svnnotify --subject-prefix [Devlist] svnnotify -P [%d (Our-Developers)] An optional string to prepend to the beginning of the subject line of the notification email. If it contains '%d', it will be used to place the revision number; otherwise it will simply be prepended to the subject, which will contain the revision number in brackets. =item subject_cx svnnotify --subject-cx svnnotify -C A boolean value indicating whether or not to include a the context of the commit in the subject line of the email. In a commit that affects multiple files, the context will be the name of the shortest directory affected by the commit. This should indicate up to how high up the Subversion repository tree the commit had an effect. If the commit affects a single file, then the context will simply be the name of that file. =item strip_cx_regex svnnotify --strip-cx-regex '^trunk/' svnnotify --strip-cx-regex '^trunk/' --strip-cx-regex '^branches/' svnnotify -X '^trunk' svnnotify -X '^trunk' -X '^branches' One or more regular expressions to be used to strip out parts of the subject context. This can be useful for very deep Subversion trees, where the commits you're sending will always be sent from a particular subtree, so you'd like to remove part of the tree. Used only if C is set to a true value. Pass an array reference if calling C directly. =item no_first_line svnnotify --no-first-line svnnotify -O Omits the first line of the log message from the subject. This is most useful when used in combination with the C parameter, so that just the commit context is displayed in the subject and no part of the log message. =item header svnnotify --header 'SVN::Notify is brought to you by Kineticode. Adds a specified text to each message as a header at the beginning of the body of the message. Not to be confused with the C<--add-header> option, which adds a header to the headers section of the email. =item footer svnnotify --footer 'Copyright (R) by Kineticode, Inc.' Adds a specified text to each message as a footer at the end of the body of the message. =item max_sub_length svnnotify --max-sub-length 72 svnnotify -i 76 The maximum length of the notification email subject line. SVN::Notify includes the first line of the commit log message, or the first sentence of the message (defined as any text up to the string ". "), whichever is shorter. This could potentially be quite long. To prevent the subject from being over a certain number of characters, specify a maximum length here, and SVN::Notify will truncate the subject to the last word under that length. =item max_diff_length svnnotify --max-diff-length 1024 The maximum length of the diff (attached or in the body). The diff output is truncated at the last line under the maximum character count specified and then outputs an additional line indicating that the maximum diff size was reached and output truncated. This is helpful when a large diff output could cause a message to bounce due to message size. =item handler svnnotify --handler HTML svnnotify -H HTML Specify the subclass of SVN::Notify to be constructed and returned, and therefore to handle the notification. Of course you can just use a subclass directly, but this parameter is designed to make it easy to just use C<< SVN::Notify->new >> without worrying about loading subclasses, such as in F. Be sure to read the documentation for your subclass of choice, as there may be additional parameters and existing parameters may behave differently. =item filters svnnotify --filter Trac -F My::Filter SVN::Notify->new( %params, filters => ['Markdown', 'My::Filter'] ); Specify a more module to be loaded in the expectation that it defines output filters. For example, L loads a filter that converts log messages from Trac's markup format to HTML. L, available on CPAN, does the same for Markdown format. Check CPAN for other SVN::Notify filter modules. This command-line option can be specified more than once to load multiple filters. The C parameter to C should be an array reference of modules names. If a value contains "::", it is assumed to be a complete module name. Otherwise, it is assumed to be in the SVN::Notify::Filter name space. See L for details on writing your own output filters (it's really easy, I promise!). =item author_url svnnotify --author-url 'http://svn.example.com/changelog/~author=%s/repos' svnnotify --A 'mailto:%s@example.com' If a URL is specified for this parameter, then it will be used to create a link for the current author. The URL can have the "%s" format where the author's username should be put into the URL. =item revision_url svnnotify --revision-url 'http://svn.example.com/changelog/?cs=%s' svnnotify -U 'http://svn.example.com/changelog/?cs=%s' If a URL is specified for this parameter, then it will be used to create a link to the Subversion browser URL corresponding to the current revision number. It will also be used to create links to any other revision numbers mentioned in the commit message. The URL must have the "%s" format where the Subversion revision number should be put into the URL. =item svnweb_url svnnotify --svnweb-url 'http://svn.example.com/index.cgi/revision/?rev=%s' svnnotify -S 'http://svn.example.net/index.cgi/revision/?rev=%s' Deprecated. Use C instead. =item viewcvs_url svnnotify --viewcvs-url 'http://svn.example.com/viewcvs/?rev=%s&view=rev' Deprecated. Use C instead. =item ticket_map svnnotify --ticket-map '\[?#\s*(\d+)\s*\]?=http://example.com/ticket?id=%s' \ --ticket-map 'rt=http://rt.cpan.org/NoAuth/Bugs.html?id=%s' \ --ticket-map '\b([A-Z0-9]+-\d+)\b=http://jira/browse/%s' Specifies a mapping between a regular expression and a URL. The regular expression should return a single match to be interpolated into the URL, which should be a C format using "%s" to place the match (usually the ticket identifier) from the regex. The command-line option may be specified any number of times for different ticketing systems. To the API, it must be passed as a hash reference. The first example matches "[#1234]" or "#1234" or "[# 1234]". This regex should be as specific as possible, preferably wrapped in "\b" to match word boundaries. If you're using L, be sure to read its documentation for a different regular expression requirement! Optionally, the key value can be a placeholder for a regular expression used internally by SVN::Notify to match strings typically used for well-known ticketing systems. Those keys are: =over =item rt Matches Request Tracker (RT) ticket references of the form "Ticket # 12", "ticket 6", "RT # 52", "rt 52", "RT-Ticket # 213" or even "Ticket#1066". =item bugzilla Matches Bugzilla bug references of the form "Bug # 12" or "bug 6" or even "Bug#1066". =item jira Matches JIRA references of the form "JRA-1234". =item gnats Matches GnatsWeb references of the form "PR 1234". =back =item rt_url svnnotify --rt-url 'http://rt.cpan.org/NoAuth/Bugs.html?id=%s' svnnotify -T 'http://rt.perl.org/NoAuth/Bugs.html?id=%s' A shortcut for C<--ticket-map 'rt=$url'> provided for backwards compatibility. =item bugzilla_url svnnotify --bugzilla-url 'http://bugzilla.mozilla.org/show_bug.cgi?id=%s' svnnotify -B 'http://bugs.bricolage.cc/show_bug.cgi?id=%s' A shortcut for C<--ticket-map 'bugzilla=$url'> provided for backwards compatibility. =item jira_url svnnotify --jira-url 'http://jira.atlassian.com/secure/ViewIssue.jspa?key=%s' svnnotify -J 'http://nagoya.apache.org/jira/secure/ViewIssue.jspa?key=%s' A shortcut for C<--ticket-map 'jira=$url'> provided for backwards compatibility. =item gnats_url svnnotify --gnats-url 'http://gnatsweb.example.com/cgi-bin/gnatsweb.pl?cmd=view&pr=%s' svnnotify -G 'http://gnatsweb.example.com/cgi-bin/gnatsweb.pl?cmd=view&pr=%s' A shortcut for C<--ticket-map 'gnats=$url'> provided for backwards compatibility. =item ticket_url svnnotify --ticket-url 'http://ticket.example.com/showticket.html?id=%s' Deprecated. Use C, instead. =item ticket_regex svnnotify --ticket-regex '\[?#\s*(\d+)\s*\]?' Deprecated. Use C, instead. =item verbose svnnotify --verbose -V A value between 0 and 3 specifying how verbose SVN::Notify should be. The default is 0, meaning that SVN::Notify will be silent. A value of 1 causes SVN::Notify to output some information about what it's doing, while 2 and 3 each cause greater verbosity. To set the verbosity on the command line, simply pass the C<--verbose> or C<-V> option once for each level of verbosity, up to three times. Output from SVN::Notify is sent to C. =item boundary The boundary to use between email body text and attachments. This is normally generated by SVN::Notify. =item subject The subject of the email to be sent. This attribute is normally generated by C. =back =cut # XXX Sneakily used by SVN::Notify::HTML. Change to use class methods? our %_ticket_regexen = ( rt => '\b((?:rt|(?:rt-)?ticket:?)\s*#?\s*(\d+))\b', bugzilla => '\b(bug\s*#?\s*(\d+))\b', jira => '\b([A-Z0-9]+-\d+)\b', gnats => '\b(PR\s*(\d+))\b', ); sub new { my ($class, %params) = @_; # Delegate to a subclass if requested. if (my $handler = delete $params{handler}) { my $subclass = __PACKAGE__ . "::$handler"; unless ($subclass eq $class) { eval "require $subclass" or die $@; return $subclass->new(%params); } } # Load any filters. $params{filters} ||= {}; if (ref $params{filters} eq 'ARRAY') { my $filts = {}; for my $pkg ( @{ $params{filters} } ) { $pkg = "SVN::Notify::Filter::$pkg" if $pkg !~ /::/; if ($filters{$pkg}) { while (my ($k, $v) = each %{ $filters{$pkg} }) { $filts->{$k} ||= []; push @{ $filts->{$k} }, $v; } } else { eval "require $pkg" or die $@; $filters{$pkg} = {}; no strict 'refs'; while ( my ($k, $v) = each %{ "$pkg\::" } ) { my $code = *{$v}{CODE} or next; $filters{$pkg}->{$k} = $code; $filts->{$k} ||= []; push @{ $filts->{$k} }, $code; } } } $params{filters} = $filts; } # Make sure that the tos are an arrayref. $params{to} = [ $params{to} || () ] unless ref $params{to}; # Check for required parameters. $class->_dbpnt( "Checking required parameters to new()") if $params{verbose}; _usage( qq{Missing required "repos_path" parameter} ) unless $params{repos_path}; _usage( qq{Missing required "revision" parameter} ) unless $params{revision}; # Set up default values. $params{svnlook} ||= $ENV{SVNLOOK} || $class->find_exe('svnlook'); $params{with_diff} ||= $params{attach_diff}; $params{verbose} ||= 0; $params{encoding} ||= $params{charset} || 'UTF-8'; $params{svn_encoding} ||= $params{encoding}; $params{diff_encoding} ||= $params{svn_encoding}; $params{diff_content_type} ||= $params{diff_content_type} || 'text/plain'; $params{sendmail} ||= $ENV{SENDMAIL} || $class->find_exe('sendmail') unless $params{smtp}; _usage( qq{Cannot find sendmail and no "smtp" parameter specified} ) unless $params{sendmail} || $params{smtp}; # Set up the environment locale. if ( $params{language} && !$ENV{LANG} ) { ( my $lang_country = $params{language} ) =~ s/-/_/g; for my $p (qw(encoding svn_encoding)) { my $encoding = $params{$p}; $encoding =~ s/-//g if uc($encoding) ne 'UTF-8'; (my $label = $p ) =~ s/(_?)encoding/$1/; $params{"${label}env_lang"} = "$lang_country.$encoding"; } } # Set up the revision URL. $params{revision_url} ||= delete $params{svnweb_url} || delete $params{viewcvs_url}; if ($params{revision_url} && $params{revision_url} !~ /%s/) { warn "--revision-url must have '%s' format\n"; $params{revision_url} .= '/revision/?rev=%s&view=rev' } # Set up the issue tracking links. my $track = $params{ticket_map}; if ($params{ticket_regex}) { $track->{ delete $params{ticket_regex} } = delete $params{ticket_url}; } for my $system (qw(rt bugzilla jira gnats)) { my $param = $system . '_url'; if ($params{ $param }) { $track->{ $system } = delete $params{ $param }; warn "--$system-url must have '%s' format\n" unless $track->{ $system } =~ /%s/; } } $params{ticket_map} = $track if $track; # Make it so! $class->_dbpnt( "Instantiating $class object") if $params{verbose}; return bless \%params, $class; } ############################################################################## =head2 Class Methods =head3 content_type my $content_type = SVN::Notify->content_type; Returns the content type of the notification message, "text/plain". Used to set the Content-Type header for the message. =cut sub content_type { 'text/plain' } ############################################################################## =head3 register_attributes SVN::Notify::Subclass->register_attributes( foo_attr => 'foo-attr=s', bar => 'bar', bat => undef, ); This class method is used by subclasses to register new attributes. Pass in a list of key/value pairs, where the keys are the attribute names and the values are option specifications in the format required by Getopt::Long. SVN::Notify will create accessors for each attribute, and if the corresponding value is defined, it will be used by the C class method to get a command-line option value. See for an example usage of C. =cut my %OPTS; sub register_attributes { my $class = shift; my @attrs; while (@_) { push @attrs, shift; if (my $opt = shift) { $OPTS{$attrs[-1]} = $opt; } } $class->_accessors(@attrs); } ############################################################################## =head3 get_options my $options = SVN::Notify->get_options; Parses the command-line options in C<@ARGV> to a hash reference suitable for passing as the parameters to C. See L<"new"> for a complete list of the supported parameters and their corresponding command-line options. This method use Getopt::Long to parse C<@ARGV>. It then looks for any C and C options and, if it finds any, loads the appropriate classes and parses any options they requires from C<@ARGV>. Subclasses and filter classes should use C to register any attributes and options they require. After that, on Perl 5.8 and later, it decodes all of the string option from the encoding specified by the C option or UTF-8. This allows options to be passed to SVN::Notify in that encoding and end up being displayed properly in the resulting notification message. =cut sub get_options { my $class = shift; my $opts = {}; require Getopt::Long; # Enable bundling and, at the same time, case-sensitive matching of # single character options. Also enable pass-through so that subclasses # can grab more options. Getopt::Long::Configure (qw(bundling pass_through)); # Get options. Getopt::Long::GetOptions( 'repos-path|p=s' => \$opts->{repos_path}, 'revision|r=s' => \$opts->{revision}, 'to|t=s@' => \$opts->{to}, 'to-regex-map|x=s%' => \$opts->{to_regex_map}, 'to-email-map=s%' => \$opts->{to_email_map}, 'from|f=s' => \$opts->{from}, 'user-domain|D=s' => \$opts->{user_domain}, 'svnlook|l=s' => \$opts->{svnlook}, 'sendmail|s=s' => \$opts->{sendmail}, 'set-sender|E' => \$opts->{set_sender}, 'smtp=s' => \$opts->{smtp}, 'smtp-port=i' => \$opts->{smtp_port}, 'smtp-tls!' => \$opts->{smtp_tls}, 'encoding|charset|c=s'=> \$opts->{encoding}, 'diff-encoding=s' => \$opts->{diff_encoding}, 'svn-encoding=s' => \$opts->{svn_encoding}, 'language|g=s' => \$opts->{language}, 'with-diff|d' => \$opts->{with_diff}, 'attach-diff|a' => \$opts->{attach_diff}, 'diff-switches|w=s' => \$opts->{diff_switches}, 'diff-content-type=s' => \$opts->{diff_content_type}, 'reply-to|R=s' => \$opts->{reply_to}, 'subject-prefix|P=s' => \$opts->{subject_prefix}, 'subject-cx|C' => \$opts->{subject_cx}, 'strip-cx-regex|X=s@' => \$opts->{strip_cx_regex}, 'no-first-line|O' => \$opts->{no_first_line}, 'max-sub-length|i=i' => \$opts->{max_sub_length}, 'max-diff-length|e=i' => \$opts->{max_diff_length}, 'handler|H=s' => \$opts->{handler}, 'filter|F=s@' => \$opts->{filters}, 'author-url|A=s' => \$opts->{author_url}, 'ticket-regex=s' => \$opts->{ticket_regex}, 'ticket-map=s%' => \$opts->{ticket_map}, 'verbose|V+' => \$opts->{verbose}, 'help|h' => \$opts->{help}, 'man|m' => \$opts->{man}, 'version|v' => \$opts->{version}, 'header=s' => \$opts->{header}, 'footer=s' => \$opts->{footer}, 'smtp-user=s' => \$opts->{smtp_user}, 'smtp-pass=s' => \$opts->{smtp_pass}, 'smtp-authtype=s' => \$opts->{smtp_authtype}, 'add-header=s%' => sub { shift; push @{ $opts->{add_headers}{+shift} }, shift }, 'revision-url|U|svnweb-url|S|viewcvs-url=s' => \$opts->{revision_url}, 'rt-url|T|bugzilla-url|B|jira-url|J|gnats-url|G|ticket-url=s' => \$opts->{ticket_url}, ) or return; # Load a subclass if one has been specified. if (my $hand = $opts->{handler}) { eval "require " . __PACKAGE__ . "::$hand" or die $@; if ($hand eq 'Alternative') { # Load the alternative subclasses. Getopt::Long::GetOptions( map { delete $OPTS{$_} => \$opts->{$_} } keys %OPTS ); for my $alt (@{ $opts->{alternatives} || ['HTML']}) { eval "require " . __PACKAGE__ . "::$alt" or die $@; } } } # Load any filters. if ($opts->{filters}) { for my $pkg ( @{ $opts->{filters} } ) { $pkg = "SVN::Notify::Filter::$pkg" if $pkg !~ /::/; eval "require $pkg" or die $@; } } # Disallow pass-through so that any invalid options will now fail. Getopt::Long::Configure (qw(no_pass_through)); my @to_decode; if (%OPTS) { # Get a list of string options we'll need to decode. @to_decode = map { $OPTS{$_} } grep { /=s$/ } keys %OPTS if PERL58; # Load any other options. Getopt::Long::GetOptions( map { delete $OPTS{$_} => \$opts->{$_} } keys %OPTS ); } else { # Call GetOptions() again so that invalid options will be properly # caught. Getopt::Long::GetOptions(); } if (PERL58) { # Decode all string options. my $encoding = $opts->{encoding} || 'UTF-8'; for my $opt ( qw( repos_path revision from user_domain svnlook sendmail smtp smtp_tls smtp_port diff_switches reply_to subject_prefix handler author_url ticket_regex header footer smtp_user smtp_pass revision_url ticket_url ), @to_decode ) { $opts->{$opt} = Encode::decode( $encoding, $opts->{$opt} ) if $opts->{$opt}; } } # Clear the extra options specifications and return. %OPTS = (); return $opts; } ############################################################################## =head3 file_label_map my $map = SVN::Notify->file_label_map; Returns a hash reference of the labels to be used for the lists of files. A hash reference of file lists is stored in the C attribute after C has been called. The hash keys in that list correspond to Subversion status codes, and these are mapped to their appropriate labels by the hash reference returned by this method: { U => 'Modified Paths', A => 'Added Paths', D => 'Removed Paths', _ => 'Property Changed' } =cut sub file_label_map { \%map } ############################################################################## =head3 find_exe my $exe = SVN::Notify->find_exe($exe_name); This method searches through the system path, as well as the extra directories F and F (because they're common paths for C and C for an executable file with the name C<$exe_name>. The first one it finds is returned with its full path. If none is found, C returns undef. =cut sub find_exe { my ($class, $exe) = @_; $exe .= '.exe' if WIN32; require File::Spec; require Config; for my $path ( File::Spec->path, qw(/usr/local/bin /usr/bin /usr/sbin), 'C:\\program files\\subversion\\bin', $Config::Config{installbin}, $Config::Config{installscript}, ) { my $file = File::Spec->catfile($path, $exe); return $file if -f $file && -x _; } return; } ############################################################################## =head1 Instance Interface =head2 Instance Methods =head3 prepare $notifier->prepare; Prepares the SVN::Notify object, collecting all the data it needs in preparation for sending the notification email. Really it's just a shortcut for: $notifier->prepare_recipients; $notifier->prepare_contents; $notifier->prepare_files; $notifier->prepare_subject; Only it returns after the call to C if there are no recipients (that is, as when recipients are specified solely by the C or C parameter and none of the regular expressions match any of the affected directories). =cut sub prepare { my $self = shift; $self->run_filters('pre_prepare'); _usage( qq{Missing required "to", "to_regex_map", or "to_email_map" parameter} ) unless @{$self->{to}} || $self->{to_regex_map} || $self->{to_email_map}; $self->prepare_recipients; return $self unless @{ $self->{to} }; $self->prepare_contents; $self->prepare_files; $self->prepare_subject; $self->run_filters('post_prepare'); return $self; } ############################################################################## =head3 prepare_recipients $notifier->prepare_recipients; Collects and prepares a list of the notification recipients. The recipients are a combination of the value passed to the C parameter as well as any email addresses specified as keys in the hash reference passed C parameter or values passed to the C parameter, where the corresponding regular expressions stored in the hash matches one or more of the names of the directories affected by the commit. If the F parameter to C has a true value, C also determines the directory name to use for the context. =cut sub prepare_recipients { my $self = shift; $self->_dbpnt( "Preparing recipients list") if $self->{verbose}; unless ( $self->{to_regex_map} || $self->{subject_cx} || $self->{to_email_map} ) { $self->{to} = $self->run_filters( recipients => $self->{to} ); return $self; } # Prevent duplication. my $tos = $self->{to} = [ @{ $self->{to} } ]; my $regexen = $self->{to_regex_map} && $self->{to_email_map} ? [ %{ $self->{to_regex_map} }, reverse %{ $self->{to_email_map } } ] : $self->{to_regex_map} ? [ %{ $self->{to_regex_map} } ] : $self->{to_email_map} ? [ reverse %{ $self->{to_email_map } } ] : undef; if ($regexen) { $self->_dbpnt( "Compiling regex_map regular expressions") if $self->{verbose} > 1; for (my $i = 1; $i < @$regexen; $i += 2) { $self->_dbpnt( qq{Compiling "$_"}) if $self->{verbose} > 2; # Remove initial slash and compile. $regexen->[$i] =~ s|^\^[/\\]|^|; $regexen->[$i] = qr/$regexen->[$i]/; } } else { $regexen = []; } local $ENV{LANG} = "$self->{svn_env_lang}" if $self->{svn_env_lang}; my $fh = $self->_pipe( $self->{svn_encoding}, '-|', $self->{svnlook}, 'changed', $self->{repos_path}, '-r', $self->{revision}, ); # Read in a list of the files changed. my ($cx, %seen); while (<$fh>) { s/^.\s*//; s/[\n\r\/\\]+$//; for (my $i = 0; $i < @$regexen; $i += 2) { my ($email, $rx) = @{$regexen}[$i, $i + 1]; # If the file matches the regex, save the email. if (/$rx/) { $self->_dbpnt( qq{"$_" matched $rx}) if $self->{verbose} > 2; push @$tos, $email unless $seen{$email}++; } } # Grab the context if it's needed for the subject. if ($self->{subject_cx}) { # XXX Do we need to set utf8 here? my $l = length; $cx ||= $_; $cx =~ s{[/\\]?[^/\\]+$}{} until !$cx || m{^\Q$cx\E(?:$|/|\\)}; } } $self->_dbpnt( qq{Context is "$cx"}) if $self->{subject_cx} && $self->{verbose} > 1; close $fh or warn "Child process exited: $?\n"; $self->{cx} = $cx; $tos = $self->run_filters( recipients => $tos ); $self->_dbpnt( 'Recipients: "', join(', ', @$tos), '"') if $self->{verbose} > 1; return $self; } ############################################################################## =head3 prepare_contents $notifier->prepare_contents; Prepares the contents of the commit message, including the name of the user who triggered the commit (and therefore the contents of the "From" header to be used in the email) and the log message. =cut sub prepare_contents { my $self = shift; $self->_dbpnt( "Preparing contents") if $self->{verbose}; local $ENV{LANG} = "$self->{svn_env_lang}" if $self->{svn_env_lang}; my $lines = $self->_read_pipe($self->{svnlook}, 'info', $self->{repos_path}, '-r', $self->{revision}); $self->{user} = shift @$lines; $self->{date} = shift @$lines; $self->{message_size} = shift @$lines; $self->{message} = $lines; # Set up the from address. unless ($self->{from}) { $self->{from} = $self->{user} . ( $self->{user_domain} ? "\@$self->{user_domain}" : '' ); } $self->{from} = $self->run_filters( from => $self->{from} ); if ($self->{verbose} > 1) { $self->_dbpnt( "From: $self->{from}"); $self->_dbpnt( "Message: @$lines"); } return $self; } ############################################################################## =head3 prepare_files $notifier->prepare_files; Prepares the lists of files affected by the commit, sorting them into their categories: modified files, added files, and deleted files. It also compiles a list of files wherein a property was set, which might have some overlap with the list of modified files (if a single commit both modified a file and set a property on it). If the C parameter was specified and a single file was affected by the commit, then C will also specify that file name as the context to be used in the subject line of the commit email. =cut sub prepare_files { my $self = shift; $self->_dbpnt( "Preparing file lists") if $self->{verbose}; my %files; local $ENV{LANG} = "$self->{svn_env_lang}" if $self->{svn_env_lang}; my $fh = $self->_pipe( $self->{svn_encoding}, '-|', $self->{svnlook}, 'changed', $self->{repos_path}, '-r', $self->{revision}, ); # Read in a list of changed files. my $cx = $_ = <$fh>; do { s/[\n\r]+$//; if (s/^(.)(.)\s+//) { $self->_dbpnt( "$1,$2 => $_") if $self->{verbose} > 2; push @{$files{$1}}, $_; push @{$files{_}}, $_ if $2 ne ' ' && $1 ne '_'; } } while (<$fh>); if ($self->{subject_cx} && $. == 1) { # There's only one file; it's the context. $cx =~ s/[\n\r]+$//; ($self->{cx} = $cx) =~ s/^..\s+//; $self->_dbpnt( qq{File context is "$self->{cx}"}) if $self->{verbose} > 1; } # Wait till we get here to close the file handle, otherwise $. gets reset # to 0! close $fh or warn "Child process exited: $?\n"; $self->{files} = \%files; return $self; } ############################################################################## =head3 prepare_subject $notifier->prepare_subject; Prepares the subject line for the notification email. This method B be called after C and C, since each of those methods potentially sets up the context for use in the the subject line. The subject may have a prefix defined by the C parameter to C, it has the revision number, it might have the context if the C specified a true value, and it will have the first sentence or line of the commit, whichever is shorter. The subject may then be truncated to the maximum length specified by the C parameter. =cut sub prepare_subject { my $self = shift; $self->_dbpnt( "Preparing subject") if $self->{verbose}; $self->{subject} = ''; # Start with the optional message and revision number.. if ( defined $self->{subject_prefix} ) { if ( index($self->{subject_prefix}, '%d') > 0 ) { $self->{subject} .= sprintf $self->{subject_prefix}, $self->{revision}; } else { $self->{subject} .= $self->{subject_prefix} . "[$self->{revision}] "; } } else { $self->{subject} .= "[$self->{revision}] "; } # Add the context if there is one. if ($self->{cx}) { if (my $rx = $self->{strip_cx_regex}) { $self->{cx} =~ s/$_// for @$rx; } my $space = $self->{no_first_line} ? '' : ': '; $self->{subject} .= $self->{cx} . $space if $self->{cx}; } # Add the first sentence/line from the log message. unless ($self->{no_first_line}) { # Truncate to first period after a minimum of 10 characters. my $min = length $self->{message}[0]; $min = 10 if $min > 10; my $i = index substr($self->{message}[0], $min), '. '; $self->{subject} .= $i > 0 ? substr($self->{message}[0], 0, $i + 11) : $self->{message}[0]; } # Truncate to the last word under 72 characters. $self->{subject} =~ s/^(.{0,$self->{max_sub_length}})\s+.*$/$1/m if $self->{max_sub_length} && length $self->{subject} > $self->{max_sub_length}; # Now filter it. $self->{subject} = $self->run_filters( subject => $self->{subject} ); $self->_dbpnt( qq{Subject is "$self->{subject}"}) if $self->{verbose}; return $self; } ############################################################################## =head3 execute $notifier->execute; Sends the notification message. This involves opening a file handle to F or a tied file handle connected to an SMTP server and passing it to C. This is the main method used to send notifications or execute any other actions in response to Subversion activity. =cut sub execute { my $self = shift; $self->_dbpnt( "Sending message") if $self->{verbose}; $self->run_filters('pre_execute'); return $self unless @{ $self->{to} }; my $out = $self->{smtp} ? SVN::Notify::SMTP->get_handle($self) : do { local $ENV{LANG} = $self->{env_lang} if $self->{env_lang}; $self->_pipe( $self->{encoding}, '|-', $self->{sendmail}, '-oi', '-t', ($self->{set_sender} ? ('-f', $self->{from}) : ()) ); }; # Output the message. $self->output($out); close $out or warn "Child process exited: $?\n"; $self->_dbpnt( 'Message sent' ) if $self->{verbose}; $self->run_filters('post_execute'); return $self; } ############################################################################## =head3 output $notifier->output($file_handle); $notifier->output($file_handle, $no_headers); Called internally by C to output a complete email message. The file a file handle, so that C and its related methods can print directly to the email message. The optional second argument, if true, will suppress the output of the email headers. Really C is a simple wrapper around a number of other method calls. It is thus essentially a shortcut for: $notifier->output_headers($out) unless $no_headers; $notifier->output_content_type($out); $notifier->start_body($out); $notifier->output_metadata($out); $notifier->output_log_message($out); $notifier->output_file_lists($out); if ($notifier->with_diff) { my $diff_handle = $self->diff_handle; if ($notifier->attach_diff) { $notifier->end_body($out); $notifier->output_attached_diff($out, $diff_handle); } else { $notifier->output_diff($out, $diff_handle); $notifier->end_body($out); } } else { $notifier->end_body($out); } $notifier->end_message($out); =cut sub output { my ($self, $out, $no_headers) = @_; $self->_dbpnt( "Outputting notification message") if $self->{verbose} > 1; $self->output_headers($out) unless $no_headers; $self->output_content_type($out); $self->start_body($out); $self->output_metadata($out); $self->output_log_message($out); $self->output_file_lists($out); if ($self->{with_diff}) { # Get a handle on the diff output. my $diff = $self->diff_handle; if ($self->{attach_diff}) { $self->end_body($out); $self->output_attached_diff($out, $diff); } else { $self->output_diff($out, $diff); $self->end_body($out); } } else { $self->end_body($out); } $self->end_message($out); return $self; } ############################################################################## =head3 output_headers $notifier->output_headers($file_handle); Outputs the headers for the notification message headers. Should be called only once for a single email message. =cut sub output_headers { my ($self, $out) = @_; $self->_dbpnt( "Outputting headers") if $self->{verbose} > 2; # Q-Encoding (RFC 2047) my ($subj, $from, $to) = PERL58 ? map { Encode::encode( 'MIME-Q', $_ ); } $self->{subject}, $self->{from}, join ', ', @{ $self->{to} } : ( $self->{subject}, $self->{from}, join ', ', @{ $self->{to} } ); my @headers = ( "MIME-Version: 1.0\n", "X-Mailer: SVN::Notify " . $self->VERSION . ": http://search.cpan.org/dist/SVN-Notify/\n", "From: $from\n", "Errors-To: $from\n", "To: $to\n", "Subject: $subj\n" ); push @headers, "Reply-To: $self->{reply_to}\n" if $self->{reply_to}; if (my $heads = $self->{add_headers}) { while (my ($k, $v) = each %{ $heads }) { push @headers, "$k: $_\n" for ref $v ? @{ $v } : $v; } } print $out @{ $self->run_filters( headers => \@headers ) }; return $self; } ############################################################################## =head3 output_content_type $notifier->output_content_type($file_handle); Outputs the content type and transfer encoding headers. These demarcate the body of the message. If the C parameter was set to true, then a boundary string will be generated and the Content-Type set to "multipart/mixed" and stored as the C attribute. After that, this method outputs the content type returned by C, the character set specified by the C attribute, and a Content-Transfer-Encoding of "8bit". Subclasses can either rely on this functionality or override this method to provide their own content type headers. =cut sub output_content_type { my ($self, $out) = @_; $self->_dbpnt( "Outputting content type") if $self->{verbose} > 2; # Output the content type. if ($self->{attach_diff}) { # We need a boundary string. $self->{boundary} ||= join '', ('a'..'z', 'A'..'Z', 0..9)[ map { rand 62 } 0..10]; print $out qq{Content-Type: multipart/mixed; boundary="$self->{boundary}"\n\n}; } my $ctype = $self->content_type; print $out "--$self->{boundary}\n" if $self->{attach_diff}; print $out "Content-Type: $ctype; charset=$self->{encoding}\n", ($self->{language} ? "Content-Language: $self->{language}\n" : ()), "Content-Transfer-Encoding: 8bit\n\n"; return $self; } ############################################################################## =head3 start_body $notifier->start_body($file_handle); This method starts the body of the notification message, which means that it outputs the contents of the C
attribute, if there are any. Otherwise it outputs nothing, but see subclasses for other behaviors. =cut sub start_body { my ($self, $out) = @_; my $start = [ $self->{header} ? ("$self->{header}\n") : () ]; $start = $self->run_filters( start_body => $start ); print $out @$start, "\n" if $start && @$start; return $self; } ############################################################################## =head3 output_metadata $notifier->output_metadata($file_handle); This method outputs the metadata of the commit, including the revision number, author (user), and date of the revision. If the C or C attributes have been set, then the appropriate URL(s) for the revision will also be output. =cut sub output_metadata { my ($self, $out) = @_; my @lines = ("Revision: $self->{revision}\n"); if (my $url = $self->{revision_url}) { push @lines, sprintf " $url\n", $self->{revision}; } # Output the Author any any relevant URL. push @lines, "Author: $self->{user}\n"; if (my $url = $self->{author_url}) { push @lines, sprintf " $url\n", $self->{user}; } push @lines, "Date: $self->{date}\n"; print $out @{ $self->run_filters( metadata => \@lines ) }; return $self; } ############################################################################## =head3 output_log_message $notifier->output_log_message($file_handle); Outputs the commit log message, as well as the label "Log Message". =cut sub output_log_message { my ($self, $out) = @_; $self->_dbpnt( "Outputting log message") if $self->{verbose} > 1; my $msg = join "\n", @{ $self->run_filters( log_message => $self->{message} ) }; print $out "Log Message:\n-----------\n$msg\n"; # Make Revision links. if (my $url = $self->{revision_url}) { if (my @matches = $msg =~ /\b(?:(?:rev(?:ision)?\s*#?\s*|r)(\d+))\b/ig) { print $out "\nRevision Links:\n--------------\n"; printf $out " $url\n", $_ for @matches; } } # Make ticketing system links. if (my $map = $self->ticket_map) { my $has_header = 0; $self->run_ticket_map( sub { my ($regex, $url) = @_; while ($msg =~ /$regex/ig) { unless ($has_header) { print $out "\nTicket Links:\n------------\n"; $has_header = 1; } printf $out " $url\n", $2 || $1; } } ); } return $self; } ############################################################################## =head3 output_file_lists $notifier->output_file_lists($file_handle); Outputs the lists of modified, added, and deleted files, as well as the list of files for which properties were changed. The labels used for each group are pulled in from the C class method. =cut sub output_file_lists { my ($self, $out) = @_; my $files = $self->{files} or return $self; $self->_dbpnt( "Outputting file lists") if $self->{verbose} > 1; my $map = $self->file_label_map; # Create the underlines. my %dash = ( map { $_ => '-' x length($map->{$_}) } keys %$map ); foreach my $type (qw(U A D _)) { # Skip it if there's nothing to report. next unless $files->{$type}; $self->_dbpnt( " Outputting $map->{$type} file list") if $self->{verbose} > 2; # Identify the action and output each file. print $out "\n", @{ $self->run_filters( file_lists => [ "$map->{$type}:\n", "$dash{$type}\n", map { " $_\n" } @{ $files->{$type} } ] ) }; } print $out "\n"; return $self; } ############################################################################## =head3 end_body $notifier->end_body($file_handle); Closes out the body of the email by outputting the contents of the C