Merge branch 'mh/multimail'
An enhanced "post-receive" hook to send e-mail messages. * mh/multimail: post-receive-email: deprecate script in favor of git-multimail git-multimail: an improved replacement for post-receive-email
This commit is contained in:
commit
9e8a901e6b
486
contrib/hooks/multimail/README
Normal file
486
contrib/hooks/multimail/README
Normal file
@ -0,0 +1,486 @@
|
||||
git-multimail
|
||||
=============
|
||||
|
||||
git-multimail is a tool for sending notification emails on pushes to a
|
||||
Git repository. It includes a Python module called git_multimail.py,
|
||||
which can either be used as a hook script directly or can be imported
|
||||
as a Python module into another script.
|
||||
|
||||
git-multimail is derived from the Git project's old
|
||||
contrib/hooks/post-receive-email, and is mostly compatible with that
|
||||
script. See README.migrate-from-post-receive-email for details about
|
||||
the differences and for how to migrate from post-receive-email to
|
||||
git-multimail.
|
||||
|
||||
git-multimail, like the rest of the Git project, is licensed under
|
||||
GPLv2 (see the COPYING file for details).
|
||||
|
||||
Please note: although, as a convenience, git-multimail may be
|
||||
distributed along with the main Git project, development of
|
||||
git-multimail takes place in its own, separate project. See section
|
||||
"Getting involved" below for more information.
|
||||
|
||||
|
||||
By default, for each push received by the repository, git-multimail:
|
||||
|
||||
1. Outputs one email summarizing each reference that was changed.
|
||||
These "reference change" (called "refchange" below) emails describe
|
||||
the nature of the change (e.g., was the reference created, deleted,
|
||||
fast-forwarded, etc.) and include a one-line summary of each commit
|
||||
that was added to the reference.
|
||||
|
||||
2. Outputs one email for each new commit that was introduced by the
|
||||
reference change. These "commit" emails include a list of the
|
||||
files changed by the commit, followed by the diffs of files
|
||||
modified by the commit. The commit emails are threaded to the
|
||||
corresponding reference change email via "In-Reply-To". This style
|
||||
(similar to the "git format-patch" style used on the Git mailing
|
||||
list) makes it easy to scan through the emails, jump to patches
|
||||
that need further attention, and write comments about specific
|
||||
commits. Commits are handled in reverse topological order (i.e.,
|
||||
parents shown before children). For example,
|
||||
|
||||
[git] branch master updated
|
||||
+ [git] 01/08: doc: fix xref link from api docs to manual pages
|
||||
+ [git] 02/08: api-credentials.txt: show the big picture first
|
||||
+ [git] 03/08: api-credentials.txt: mention credential.helper explicitly
|
||||
+ [git] 04/08: api-credentials.txt: add "see also" section
|
||||
+ [git] 05/08: t3510 (cherry-pick-sequence): add missing '&&'
|
||||
+ [git] 06/08: Merge branch 'rr/maint-t3510-cascade-fix'
|
||||
+ [git] 07/08: Merge branch 'mm/api-credentials-doc'
|
||||
+ [git] 08/08: Git 1.7.11-rc2
|
||||
|
||||
Each commit appears in exactly one commit email, the first time
|
||||
that it is pushed to the repository. If a commit is later merged
|
||||
into another branch, then a one-line summary of the commit is
|
||||
included in the reference change email (as usual), but no
|
||||
additional commit email is generated.
|
||||
|
||||
By default, reference change emails have their "Reply-To" field set
|
||||
to the person who pushed the change, and commit emails have their
|
||||
"Reply-To" field set to the author of the commit.
|
||||
|
||||
3. Output one "announce" mail for each new annotated tag, including
|
||||
information about the tag and optionally a shortlog describing the
|
||||
changes since the previous tag. Such emails might be useful if you
|
||||
use annotated tags to mark releases of your project.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
* Python 2.x, version 2.4 or later. No non-standard Python modules
|
||||
are required. git-multimail does *not* currently work with Python
|
||||
3.x.
|
||||
|
||||
The example scripts invoke Python using the following shebang line
|
||||
(following PEP 394 [1]):
|
||||
|
||||
#! /usr/bin/env python2
|
||||
|
||||
If your system's Python2 interpreter is not in your PATH or is not
|
||||
called "python2", you can change the lines accordingly. Or you can
|
||||
invoke the Python interpreter explicitly, for example via a tiny
|
||||
shell script like
|
||||
|
||||
#! /bin/sh
|
||||
/usr/local/bin/python /path/to/git_multimail.py "$@"
|
||||
|
||||
* The "git" command must be in your PATH. git-multimail is known to
|
||||
work with Git versions back to 1.7.1. (Earlier versions have not
|
||||
been tested; if you do so, please report your results.)
|
||||
|
||||
* To send emails using the default configuration, a standard sendmail
|
||||
program must be located at '/usr/sbin/sendmail' and configured
|
||||
correctly to send emails. If this is not the case, see the
|
||||
multimailhook.mailer configuration variable below for how to
|
||||
configure git-multimail to send emails via an SMTP server.
|
||||
|
||||
|
||||
Invocation
|
||||
----------
|
||||
|
||||
git_multimail.py is designed to be used as a "post-receive" hook in a
|
||||
Git repository (see githooks(5)). Link or copy it to
|
||||
$GIT_DIR/hooks/post-receive within the repository for which email
|
||||
notifications are desired. Usually it should be installed on the
|
||||
central repository for a project, to which all commits are eventually
|
||||
pushed.
|
||||
|
||||
For use on pre-v1.5.1 Git servers, git_multimail.py can also work as
|
||||
an "update" hook, taking its arguments on the command line. To use
|
||||
this script in this manner, link or copy it to $GIT_DIR/hooks/update.
|
||||
Please note that the script is not completely reliable in this mode
|
||||
[2].
|
||||
|
||||
Alternatively, git_multimail.py can be imported as a Python module
|
||||
into your own Python post-receive script. This method is a bit more
|
||||
work, but allows the behavior of the hook to be customized using
|
||||
arbitrary Python code. For example, you can use a custom environment
|
||||
(perhaps inheriting from GenericEnvironment or GitoliteEnvironment) to
|
||||
|
||||
* change how the user who did the push is determined
|
||||
|
||||
* read users' email addresses from an LDAP server or from a database
|
||||
|
||||
* decide which users should be notified about which commits based on
|
||||
the contents of the commits (e.g., for users who want to be notified
|
||||
only about changes affecting particular files or subdirectories)
|
||||
|
||||
Or you can change how emails are sent by writing your own Mailer
|
||||
class. The "post-receive" script in this directory demonstrates how
|
||||
to use git_multimail.py as a Python module. (If you make interesting
|
||||
changes of this type, please consider sharing them with the
|
||||
community.)
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
By default, git-multimail mostly takes its configuration from the
|
||||
following "git config" settings:
|
||||
|
||||
multimailhook.environment
|
||||
|
||||
This describes the general environment of the repository.
|
||||
Currently supported values:
|
||||
|
||||
"generic" -- the username of the pusher is read from $USER and the
|
||||
repository name is derived from the repository's path.
|
||||
|
||||
"gitolite" -- the username of the pusher is read from $GL_USER and
|
||||
the repository name from $GL_REPO.
|
||||
|
||||
If neither of these environments is suitable for your setup, then
|
||||
you can implement a Python class that inherits from Environment
|
||||
and instantiate it via a script that looks like the example
|
||||
post-receive script.
|
||||
|
||||
The environment value can be specified on the command line using
|
||||
the --environment option. If it is not specified on the command
|
||||
line or by multimailhook.environment, then it defaults to
|
||||
"gitolite" if the environment contains variables $GL_USER and
|
||||
$GL_REPO; otherwise "generic".
|
||||
|
||||
multimailhook.repoName
|
||||
|
||||
A short name of this Git repository, to be used in various places
|
||||
in the notification email text. The default is to use $GL_REPO
|
||||
for gitolite repositories, or otherwise to derive this value from
|
||||
the repository path name.
|
||||
|
||||
multimailhook.mailinglist
|
||||
|
||||
The list of email addresses to which notification emails should be
|
||||
sent, as RFC 2822 email addresses separated by commas. This
|
||||
configuration option can be multivalued. Leave it unset or set it
|
||||
to the empty string to not send emails by default. The next few
|
||||
settings can be used to configure specific address lists for
|
||||
specific types of notification email.
|
||||
|
||||
multimailhook.refchangeList
|
||||
|
||||
The list of email addresses to which summary emails about
|
||||
reference changes should be sent, as RFC 2822 email addresses
|
||||
separated by commas. This configuration option can be
|
||||
multivalued. The default is the value in
|
||||
multimailhook.mailinglist. Set this value to the empty string to
|
||||
prevent reference change emails from being sent.
|
||||
|
||||
multimailhook.announceList
|
||||
|
||||
The list of email addresses to which emails about new annotated
|
||||
tags should be sent, as RFC 2822 email addresses separated by
|
||||
commas. This configuration option can be multivalued. The
|
||||
default is the value in multimailhook.refchangelist or
|
||||
multimailhook.mailinglist. Set this value to the empty string to
|
||||
prevent annotated tag announcement emails from being sent.
|
||||
|
||||
multimailhook.commitList
|
||||
|
||||
The list of email addresses to which emails about individual new
|
||||
commits should be sent, as RFC 2822 email addresses separated by
|
||||
commas. This configuration option can be multivalued. The
|
||||
default is the value in multimailhook.mailinglist. Set this value
|
||||
to the empty string to prevent notification emails about
|
||||
individual commits from being sent.
|
||||
|
||||
multimailhook.announceShortlog
|
||||
|
||||
If this option is set to true, then emails about changes to
|
||||
annotated tags include a shortlog of changes since the previous
|
||||
tag. This can be useful if the annotated tags represent releases;
|
||||
then the shortlog will be a kind of rough summary of what has
|
||||
happened since the last release. But if your tagging policy is
|
||||
not so straightforward, then the shortlog might be confusing
|
||||
rather than useful. Default is false.
|
||||
|
||||
multimailhook.refchangeShowLog
|
||||
|
||||
If this option is set to true, then summary emails about reference
|
||||
changes will include a detailed log of the added commits in
|
||||
addition to the one line summary. The log is generated by running
|
||||
"git log" with the options specified in multimailhook.logOpts.
|
||||
Default is false.
|
||||
|
||||
multimailhook.mailer
|
||||
|
||||
This option changes the way emails are sent. Accepted values are:
|
||||
|
||||
- sendmail (the default): use the command /usr/sbin/sendmail or
|
||||
/usr/lib/sendmail (or sendmailCommand, if configured). This
|
||||
mode can be further customized via the following options:
|
||||
|
||||
multimailhook.sendmailCommand
|
||||
|
||||
The command used by mailer "sendmail" to send emails. Shell
|
||||
quoting is allowed in the value of this setting, but remember that
|
||||
Git requires double-quotes to be escaped; e.g.,
|
||||
|
||||
git config multimailhook.sendmailcommand '/usr/sbin/sendmail -t -F \"Git Repo\"'
|
||||
|
||||
Default is '/usr/sbin/sendmail -t' or '/usr/lib/sendmail
|
||||
-t' (depending on which file is present and executable).
|
||||
|
||||
multimailhook.envelopeSender
|
||||
|
||||
If set then pass this value to sendmail via the -f option to set
|
||||
the envelope sender address.
|
||||
|
||||
- smtp: use Python's smtplib. This is useful when the sendmail
|
||||
command is not available on the system. This mode can be
|
||||
further customized via the following options:
|
||||
|
||||
multimailhook.smtpServer
|
||||
|
||||
The name of the SMTP server to connect to. The value can
|
||||
also include a colon and a port number; e.g.,
|
||||
"mail.example.com:25". Default is 'localhost' using port
|
||||
25.
|
||||
|
||||
multimailhook.envelopeSender
|
||||
|
||||
The sender address to be passed to the SMTP server. If
|
||||
unset, then the value of multimailhook.from is used.
|
||||
|
||||
multimailhook.from
|
||||
|
||||
If set then use this value in the From: field of generated emails.
|
||||
If unset, then use the repository's user configuration (user.name
|
||||
and user.email). If user.email is also unset, then use
|
||||
multimailhook.envelopeSender.
|
||||
|
||||
multimailhook.administrator
|
||||
|
||||
The name and/or email address of the administrator of the Git
|
||||
repository; used in FOOTER_TEMPLATE. Default is
|
||||
multimailhook.envelopesender if it is set; otherwise a generic
|
||||
string is used.
|
||||
|
||||
multimailhook.emailPrefix
|
||||
|
||||
All emails have this string prepended to their subjects, to aid
|
||||
email filtering (though filtering based on the X-Git-* email
|
||||
headers is probably more robust). Default is the short name of
|
||||
the repository in square brackets; e.g., "[myrepo]".
|
||||
|
||||
multimailhook.emailMaxLines
|
||||
|
||||
The maximum number of lines that should be included in the body of
|
||||
a generated email. If not specified, there is no limit. Lines
|
||||
beyond the limit are suppressed and counted, and a final line is
|
||||
added indicating the number of suppressed lines.
|
||||
|
||||
multimailhook.emailMaxLineLength
|
||||
|
||||
The maximum length of a line in the email body. Lines longer than
|
||||
this limit are truncated to this length with a trailing " [...]"
|
||||
added to indicate the missing text. The default is 500, because
|
||||
(a) diffs with longer lines are probably from binary files, for
|
||||
which a diff is useless, and (b) even if a text file has such long
|
||||
lines, the diffs are probably unreadable anyway. To disable line
|
||||
truncation, set this option to 0.
|
||||
|
||||
multimailhook.maxCommitEmails
|
||||
|
||||
The maximum number of commit emails to send for a given change.
|
||||
When the number of patches is larger that this value, only the
|
||||
summary refchange email is sent. This can avoid accidental
|
||||
mailbombing, for example on an initial push. To disable commit
|
||||
emails limit, set this option to 0. The default is 500.
|
||||
|
||||
multimailhook.emailStrictUTF8
|
||||
|
||||
If this boolean option is set to "true", then the main part of the
|
||||
email body is forced to be valid UTF-8. Any characters that are
|
||||
not valid UTF-8 are converted to the Unicode replacement
|
||||
character, U+FFFD. The default is "true".
|
||||
|
||||
multimailhook.diffOpts
|
||||
|
||||
Options passed to "git diff-tree" when generating the summary
|
||||
information for ReferenceChange emails. Default is "--stat
|
||||
--summary --find-copies-harder". Add -p to those options to
|
||||
include a unified diff of changes in addition to the usual summary
|
||||
output. Shell quoting is allowed; see multimailhook.logOpts for
|
||||
details.
|
||||
|
||||
multimailhook.logOpts
|
||||
|
||||
Options passed to "git log" to generate additional info for
|
||||
reference change emails (used only if refchangeShowLog is set).
|
||||
For example, adding --graph will show the graph of revisions, -p
|
||||
will show the complete diff, etc. The default is empty.
|
||||
|
||||
Shell quoting is allowed; for example, a log format that contains
|
||||
spaces can be specified using something like:
|
||||
|
||||
git config multimailhook.logopts '--pretty=format:"%h %aN <%aE>%n%s%n%n%b%n"'
|
||||
|
||||
If you want to set this by editing your configuration file
|
||||
directly, remember that Git requires double-quotes to be escaped
|
||||
(see git-config(1) for more information):
|
||||
|
||||
[multimailhook]
|
||||
logopts = --pretty=format:\"%h %aN <%aE>%n%s%n%n%b%n\"
|
||||
|
||||
multimailhook.emailDomain
|
||||
|
||||
Domain name appended to the username of the person doing the push
|
||||
to convert it into an email address (via "%s@%s" % (username,
|
||||
emaildomain)). More complicated schemes can be implemented by
|
||||
overriding Environment and overriding its get_pusher_email()
|
||||
method.
|
||||
|
||||
multimailhook.replyTo
|
||||
multimailhook.replyToCommit
|
||||
multimailhook.replyToRefchange
|
||||
|
||||
Addresses to use in the Reply-To: field for commit emails
|
||||
(replyToCommit) and refchange emails (replyToRefchange).
|
||||
multimailhook.replyTo is used as default when replyToCommit or
|
||||
replyToRefchange is not set. The value for these variables can be
|
||||
either:
|
||||
|
||||
- An email address, which will be used directly.
|
||||
|
||||
- The value "pusher", in which case the pusher's address (if
|
||||
available) will be used. This is the default for refchange
|
||||
emails.
|
||||
|
||||
- The value "author" (meaningful only for replyToCommit), in which
|
||||
case the commit author's address will be used. This is the
|
||||
default for commit emails.
|
||||
|
||||
- The value "none", in which case the Reply-To: field will be
|
||||
omitted.
|
||||
|
||||
|
||||
Email filtering aids
|
||||
--------------------
|
||||
|
||||
All emails include extra headers to enable fine tuned filtering and
|
||||
give information for debugging. All emails include the headers
|
||||
"X-Git-Repo", "X-Git-Refname", and "X-Git-Reftype". ReferenceChange
|
||||
emails also include headers "X-Git-Oldrev" and "X-Git-Newrev";
|
||||
Revision emails also include header "X-Git-Rev".
|
||||
|
||||
|
||||
Customizing email contents
|
||||
--------------------------
|
||||
|
||||
git-multimail mostly generates emails by expanding templates. The
|
||||
templates can be customized. To avoid the need to edit
|
||||
git_multimail.py directly, the preferred way to change the templates
|
||||
is to write a separate Python script that imports git_multimail.py as
|
||||
a module, then replaces the templates in place. See the provided
|
||||
post-receive script for an example of how this is done.
|
||||
|
||||
|
||||
Customizing git-multimail for your environment
|
||||
----------------------------------------------
|
||||
|
||||
git-multimail is mostly customized via an "environment" that describes
|
||||
the local environment in which Git is running. Two types of
|
||||
environment are built in:
|
||||
|
||||
* GenericEnvironment: a stand-alone Git repository.
|
||||
|
||||
* GitoliteEnvironment: a Git repository that is managed by gitolite
|
||||
[3]. For such repositories, the identity of the pusher is read from
|
||||
environment variable $GL_USER, and the name of the repository is
|
||||
read from $GL_REPO (if it is not overridden by
|
||||
multimailhook.reponame).
|
||||
|
||||
By default, git-multimail assumes GitoliteEnvironment if $GL_USER and
|
||||
$GL_REPO are set, and otherwise assumes GenericEnvironment.
|
||||
Alternatively, you can choose one of these two environments explicitly
|
||||
by setting a "multimailhook.environment" config setting (which can
|
||||
have the value "generic" or "gitolite") or by passing an --environment
|
||||
option to the script.
|
||||
|
||||
If you need to customize the script in ways that are not supported by
|
||||
the existing environments, you can define your own environment class
|
||||
class using arbitrary Python code. To do so, you need to import
|
||||
git_multimail.py as a Python module, as demonstrated by the example
|
||||
post-receive script. Then implement your environment class; it should
|
||||
usually inherit from one of the existing Environment classes and
|
||||
possibly one or more of the EnvironmentMixin classes. Then set the
|
||||
"environment" variable to an instance of your own environment class
|
||||
and pass it to run_as_post_receive_hook().
|
||||
|
||||
The standard environment classes, GenericEnvironment and
|
||||
GitoliteEnvironment, are in fact themselves put together out of a
|
||||
number of mixin classes, each of which handles one aspect of the
|
||||
customization. For the finest control over your configuration, you
|
||||
can specify exactly which mixin classes your own environment class
|
||||
should inherit from, and override individual methods (or even add your
|
||||
own mixin classes) to implement entirely new behaviors. If you
|
||||
implement any mixins that might be useful to other people, please
|
||||
consider sharing them with the community!
|
||||
|
||||
|
||||
Getting involved
|
||||
----------------
|
||||
|
||||
git-multimail is an open-source project, built by volunteers. We
|
||||
would welcome your help!
|
||||
|
||||
The current maintainer is Michael Haggerty <mhagger@alum.mit.edu>.
|
||||
|
||||
General discussion of git-multimail takes place on the main Git
|
||||
mailing list,
|
||||
|
||||
git@vger.kernel.org
|
||||
|
||||
Please CC emails regarding git-multimail to me so that I don't
|
||||
overlook them.
|
||||
|
||||
The git-multimail project itself is currently hosted on GitHub:
|
||||
|
||||
https://github.com/mhagger/git-multimail
|
||||
|
||||
We use the GitHub issue tracker to keep track of bugs and feature
|
||||
requests, and GitHub pull requests to exchange patches (though, if you
|
||||
prefer, you can send patches via the Git mailing list with cc to me).
|
||||
|
||||
Please note that although a copy of git-multimail will probably be
|
||||
distributed in the "contrib" section of the main Git project,
|
||||
development takes place in the separate git-multimail repository on
|
||||
GitHub! (Whenever enough changes to git-multimail have accumulated, a
|
||||
new code-drop of git-multimail will be submitted for inclusion in the
|
||||
Git project.)
|
||||
|
||||
|
||||
Footnotes
|
||||
---------
|
||||
|
||||
[1] http://www.python.org/dev/peps/pep-0394/
|
||||
|
||||
[2] Because of the way information is passed to update hooks, the
|
||||
script's method of determining whether a commit has already been
|
||||
seen does not work when it is used as an "update" script. In
|
||||
particular, no notification email will be generated for a new
|
||||
commit that is added to multiple references in the same push.
|
||||
|
||||
[3] https://github.com/sitaramc/gitolite
|
15
contrib/hooks/multimail/README.Git
Normal file
15
contrib/hooks/multimail/README.Git
Normal file
@ -0,0 +1,15 @@
|
||||
This copy of git-multimail is distributed as part of the "contrib"
|
||||
section of the Git project as a convenience to Git users.
|
||||
git-multimail is developed as an independent project at the following
|
||||
website:
|
||||
|
||||
https://github.com/mhagger/git-multimail
|
||||
|
||||
The version in this directory was obtained from the upstream project
|
||||
on 2013-07-14 and consists of the "git-multimail" subdirectory from
|
||||
revision
|
||||
|
||||
1a5cb09c698a74d15a715a86b09ead5f56bf4b06
|
||||
|
||||
Please see the README file in this directory for information about how
|
||||
to report bugs or contribute to git-multimail.
|
145
contrib/hooks/multimail/README.migrate-from-post-receive-email
Normal file
145
contrib/hooks/multimail/README.migrate-from-post-receive-email
Normal file
@ -0,0 +1,145 @@
|
||||
git-multimail is close to, but not exactly, a plug-in replacement for
|
||||
the old Git project script contrib/hooks/post-receive-email. This
|
||||
document describes the differences and explains how to configure
|
||||
git-multimail to get behavior closest to that of post-receive-email.
|
||||
|
||||
If you are in a hurry
|
||||
=====================
|
||||
|
||||
A script called migrate-mailhook-config is included with
|
||||
git-multimail. If you run this script within a Git repository that is
|
||||
configured to use post-receive-email, it will convert the
|
||||
configuration settings into the approximate equivalent settings for
|
||||
git-multimail. For more information, run
|
||||
|
||||
migrate-mailhook-config --help
|
||||
|
||||
|
||||
Configuration differences
|
||||
=========================
|
||||
|
||||
* The names of the config options for git-multimail are in namespace
|
||||
"multimailhook.*" instead of "hooks.*". (Editorial comment:
|
||||
post-receive-email should never have used such a generic top-level
|
||||
namespace.)
|
||||
|
||||
* In emails about new annotated tags, post-receive-email includes a
|
||||
shortlog of all changes since the previous annotated tag. To get
|
||||
this behavior with git-multimail, you need to set
|
||||
multimailhook.announceshortlog to true:
|
||||
|
||||
git config multimailhook.announceshortlog true
|
||||
|
||||
* multimailhook.commitlist -- This is a new configuration variable.
|
||||
Recipients listed here will receive a separate email for each new
|
||||
commit. However, if this variable is *not* set, it defaults to the
|
||||
value of multimailhook.mailinglist. Therefore, if you *don't* want
|
||||
the members of multimailhook.mailinglist to receive one email per
|
||||
commit, then set this value to the empty string:
|
||||
|
||||
git config multimailhook.commitlist ''
|
||||
|
||||
* multimailhook.emailprefix -- If this value is not set, then the
|
||||
subjects of generated emails are prefixed with the short name of the
|
||||
repository enclosed in square brackets; e.g., "[myrepo]".
|
||||
post-receive-email defaults to prefix "[SCM]" if this option is not
|
||||
set. So if you were using the old default and want to retain it
|
||||
(for example, to avoid having to change your email filters), set
|
||||
this variable explicitly to the old value:
|
||||
|
||||
git config multimailhook.emailprefix "[SCM]"
|
||||
|
||||
* The "multimailhook.showrev" configuration option is not supported.
|
||||
Its main use is obsoleted by the one-email-per-commit feature of
|
||||
git-multimail.
|
||||
|
||||
|
||||
Other differences
|
||||
=================
|
||||
|
||||
This section describes other differences in the behavior of
|
||||
git-multimail vs. post-receive-email. For full details, please refer
|
||||
to the main README file:
|
||||
|
||||
* One email per commit. For each reference change, the script first
|
||||
outputs one email summarizing the reference change (including
|
||||
one-line summaries of the new commits), then it outputs a separate
|
||||
email for each new commit that was introduced, including patches.
|
||||
These one-email-per-commit emails go to the addresses listed in
|
||||
multimailhook.commitlist. post-receive-email sends only one email
|
||||
for each *reference* that is changed, no matter how many commits
|
||||
were added to the reference.
|
||||
|
||||
* Better algorithm for detecting new commits. post-receive-email
|
||||
processes one reference change at a time, which causes it to fail to
|
||||
describe new commits that were included in multiple branches. For
|
||||
example, if a single push adds the "*" commits in the diagram below,
|
||||
then post-receive-email would never include the details of the two
|
||||
commits that are common to "master" and "branch" in its
|
||||
notifications.
|
||||
|
||||
o---o---o---*---*---* <-- master
|
||||
\
|
||||
*---* <-- branch
|
||||
|
||||
git-multimail analyzes all reference modifications to determine
|
||||
which commits were not present before the change, therefore avoiding
|
||||
that error.
|
||||
|
||||
* In reference change emails, git-multimail tells which commits have
|
||||
been added to the reference vs. are entirely new to the repository,
|
||||
and which commits that have been omitted from the reference
|
||||
vs. entirely discarded from the repository.
|
||||
|
||||
* The environment in which Git is running can be configured via an
|
||||
"Environment" abstraction.
|
||||
|
||||
* Built-in support for Gitolite-managed repositories.
|
||||
|
||||
* Instead of using full SHA1 object names in emails, git-multimail
|
||||
mostly uses abbreviated SHA1s, plus one-line log message summaries
|
||||
where appropriate.
|
||||
|
||||
* In the schematic diagrams that explain non-fast-forward commits,
|
||||
git-multimail shows the names of the branches involved.
|
||||
|
||||
* The emails generated by git-multimail include the name of the Git
|
||||
repository that was modified; this is convenient for recipients who
|
||||
are monitoring multiple repositories.
|
||||
|
||||
* git-multimail allows the email "From" addresses to be configured.
|
||||
|
||||
* The recipients lists (multimailhook.mailinglist,
|
||||
multimailhook.refchangelist, multimailhook.announcelist, and
|
||||
multimailhook.commitlist) can be comma-separated values and/or
|
||||
multivalued settings in the config file; e.g.,
|
||||
|
||||
[multimailhook]
|
||||
mailinglist = mr.brown@example.com, mr.black@example.com
|
||||
announcelist = Him <him@example.com>
|
||||
announcelist = Jim <jim@example.com>
|
||||
announcelist = pop@example.com
|
||||
|
||||
This might make it easier to maintain short recipients lists without
|
||||
requiring full-fledged mailing list software.
|
||||
|
||||
* By default, git-multimail sets email "Reply-To" headers to reply to
|
||||
the pusher (for reference updates) and to the author (for commit
|
||||
notifications). By default, the pusher's email address is
|
||||
constructed by appending "multimailhook.emaildomain" to the pusher's
|
||||
username.
|
||||
|
||||
* The generated emails contain a configurable footer. By default, it
|
||||
lists the name of the administrator who should be contacted to
|
||||
unsubscribe from notification emails.
|
||||
|
||||
* New option multimailhook.emailmaxlinelength to limit the length of
|
||||
lines in the main part of the email body. The default limit is 500
|
||||
characters.
|
||||
|
||||
* New option multimailhook.emailstrictutf8 to ensure that the main
|
||||
part of the email body is valid UTF-8. Invalid characters are
|
||||
turned into the Unicode replacement character, U+FFFD. By default
|
||||
this option is turned on.
|
||||
|
||||
* Written in Python. Easier to add new features.
|
2393
contrib/hooks/multimail/git_multimail.py
Executable file
2393
contrib/hooks/multimail/git_multimail.py
Executable file
File diff suppressed because it is too large
Load Diff
269
contrib/hooks/multimail/migrate-mailhook-config
Executable file
269
contrib/hooks/multimail/migrate-mailhook-config
Executable file
@ -0,0 +1,269 @@
|
||||
#! /usr/bin/env python2
|
||||
|
||||
"""Migrate a post-receive-email configuration to be usable with git_multimail.py.
|
||||
|
||||
See README.migrate-from-post-receive-email for more information.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
import optparse
|
||||
|
||||
from git_multimail import CommandError
|
||||
from git_multimail import Config
|
||||
from git_multimail import read_output
|
||||
|
||||
|
||||
OLD_NAMES = [
|
||||
'mailinglist',
|
||||
'announcelist',
|
||||
'envelopesender',
|
||||
'emailprefix',
|
||||
'showrev',
|
||||
'emailmaxlines',
|
||||
'diffopts',
|
||||
]
|
||||
|
||||
NEW_NAMES = [
|
||||
'environment',
|
||||
'reponame',
|
||||
'mailinglist',
|
||||
'refchangelist',
|
||||
'commitlist',
|
||||
'announcelist',
|
||||
'announceshortlog',
|
||||
'envelopesender',
|
||||
'administrator',
|
||||
'emailprefix',
|
||||
'emailmaxlines',
|
||||
'diffopts',
|
||||
'emaildomain',
|
||||
]
|
||||
|
||||
|
||||
INFO = """\
|
||||
|
||||
SUCCESS!
|
||||
|
||||
Your post-receive-email configuration has been converted to
|
||||
git-multimail format. Please see README and
|
||||
README.migrate-from-post-receive-email to learn about other
|
||||
git-multimail configuration possibilities.
|
||||
|
||||
For example, git-multimail has the following new options with no
|
||||
equivalent in post-receive-email. You might want to read about them
|
||||
to see if they would be useful in your situation:
|
||||
|
||||
"""
|
||||
|
||||
|
||||
def _check_old_config_exists(old):
|
||||
"""Check that at least one old configuration value is set."""
|
||||
|
||||
for name in OLD_NAMES:
|
||||
if old.has_key(name):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def _check_new_config_clear(new):
|
||||
"""Check that none of the new configuration names are set."""
|
||||
|
||||
retval = True
|
||||
for name in NEW_NAMES:
|
||||
if new.has_key(name):
|
||||
if retval:
|
||||
sys.stderr.write('INFO: The following configuration values already exist:\n\n')
|
||||
sys.stderr.write(' "%s.%s"\n' % (new.section, name))
|
||||
retval = False
|
||||
|
||||
return retval
|
||||
|
||||
|
||||
def erase_values(config, names):
|
||||
for name in names:
|
||||
if config.has_key(name):
|
||||
try:
|
||||
sys.stderr.write('...unsetting "%s.%s"\n' % (config.section, name))
|
||||
config.unset_all(name)
|
||||
except CommandError:
|
||||
sys.stderr.write(
|
||||
'\nWARNING: could not unset "%s.%s". '
|
||||
'Perhaps it is not set at the --local level?\n\n'
|
||||
% (config.section, name)
|
||||
)
|
||||
|
||||
|
||||
def is_section_empty(section, local):
|
||||
"""Return True iff the specified configuration section is empty.
|
||||
|
||||
Iff local is True, use the --local option when invoking 'git
|
||||
config'."""
|
||||
|
||||
if local:
|
||||
local_option = ['--local']
|
||||
else:
|
||||
local_option = []
|
||||
|
||||
try:
|
||||
read_output(
|
||||
['git', 'config']
|
||||
+ local_option
|
||||
+ ['--get-regexp', '^%s\.' % (section,)]
|
||||
)
|
||||
except CommandError, e:
|
||||
if e.retcode == 1:
|
||||
# This means that no settings were found.
|
||||
return True
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def remove_section_if_empty(section):
|
||||
"""If the specified configuration section is empty, delete it."""
|
||||
|
||||
try:
|
||||
empty = is_section_empty(section, local=True)
|
||||
except CommandError:
|
||||
# Older versions of git do not support the --local option, so
|
||||
# if the first attempt fails, try without --local.
|
||||
try:
|
||||
empty = is_section_empty(section, local=False)
|
||||
except CommandError:
|
||||
sys.stderr.write(
|
||||
'\nINFO: If configuration section "%s.*" is empty, you might want '
|
||||
'to delete it.\n\n'
|
||||
% (section,)
|
||||
)
|
||||
return
|
||||
|
||||
if empty:
|
||||
sys.stderr.write('...removing section "%s.*"\n' % (section,))
|
||||
read_output(['git', 'config', '--remove-section', section])
|
||||
else:
|
||||
sys.stderr.write(
|
||||
'\nINFO: Configuration section "%s.*" still has contents. '
|
||||
'It will not be deleted.\n\n'
|
||||
% (section,)
|
||||
)
|
||||
|
||||
|
||||
def migrate_config(strict=False, retain=False, overwrite=False):
|
||||
old = Config('hooks')
|
||||
new = Config('multimailhook')
|
||||
if not _check_old_config_exists(old):
|
||||
sys.exit(
|
||||
'Your repository has no post-receive-email configuration. '
|
||||
'Nothing to do.'
|
||||
)
|
||||
if not _check_new_config_clear(new):
|
||||
if overwrite:
|
||||
sys.stderr.write('\nWARNING: Erasing the above values...\n\n')
|
||||
erase_values(new, NEW_NAMES)
|
||||
else:
|
||||
sys.exit(
|
||||
'\nERROR: Refusing to overwrite existing values. Use the --overwrite\n'
|
||||
'option to continue anyway.'
|
||||
)
|
||||
|
||||
name = 'showrev'
|
||||
if old.has_key(name):
|
||||
msg = 'git-multimail does not support "%s.%s"' % (old.section, name,)
|
||||
if strict:
|
||||
sys.exit(
|
||||
'ERROR: %s.\n'
|
||||
'Please unset that value then try again, or run without --strict.'
|
||||
% (msg,)
|
||||
)
|
||||
else:
|
||||
sys.stderr.write('\nWARNING: %s (ignoring).\n\n' % (msg,))
|
||||
|
||||
for name in ['mailinglist', 'announcelist']:
|
||||
if old.has_key(name):
|
||||
sys.stderr.write(
|
||||
'...copying "%s.%s" to "%s.%s"\n' % (old.section, name, new.section, name)
|
||||
)
|
||||
new.set_recipients(name, old.get_recipients(name))
|
||||
|
||||
if strict:
|
||||
sys.stderr.write(
|
||||
'...setting "%s.commitlist" to the empty string\n' % (new.section,)
|
||||
)
|
||||
new.set_recipients('commitlist', '')
|
||||
sys.stderr.write(
|
||||
'...setting "%s.announceshortlog" to "true"\n' % (new.section,)
|
||||
)
|
||||
new.set('announceshortlog', 'true')
|
||||
|
||||
for name in ['envelopesender', 'emailmaxlines', 'diffopts']:
|
||||
if old.has_key(name):
|
||||
sys.stderr.write(
|
||||
'...copying "%s.%s" to "%s.%s"\n' % (old.section, name, new.section, name)
|
||||
)
|
||||
new.set(name, old.get(name))
|
||||
|
||||
name = 'emailprefix'
|
||||
if old.has_key(name):
|
||||
sys.stderr.write(
|
||||
'...copying "%s.%s" to "%s.%s"\n' % (old.section, name, new.section, name)
|
||||
)
|
||||
new.set(name, old.get(name))
|
||||
elif strict:
|
||||
sys.stderr.write(
|
||||
'...setting "%s.%s" to "[SCM]" to preserve old subject lines\n'
|
||||
% (new.section, name)
|
||||
)
|
||||
new.set(name, '[SCM]')
|
||||
|
||||
if not retain:
|
||||
erase_values(old, OLD_NAMES)
|
||||
remove_section_if_empty(old.section)
|
||||
|
||||
sys.stderr.write(INFO)
|
||||
for name in NEW_NAMES:
|
||||
if name not in OLD_NAMES:
|
||||
sys.stderr.write(' "%s.%s"\n' % (new.section, name,))
|
||||
sys.stderr.write('\n')
|
||||
|
||||
|
||||
def main(args):
|
||||
parser = optparse.OptionParser(
|
||||
description=__doc__,
|
||||
usage='%prog [OPTIONS]',
|
||||
)
|
||||
|
||||
parser.add_option(
|
||||
'--strict', action='store_true', default=False,
|
||||
help=(
|
||||
'Slavishly configure git-multimail as closely as possible to '
|
||||
'the post-receive-email configuration. Default is to turn '
|
||||
'on some new features that have no equivalent in post-receive-email.'
|
||||
),
|
||||
)
|
||||
parser.add_option(
|
||||
'--retain', action='store_true', default=False,
|
||||
help=(
|
||||
'Retain the post-receive-email configuration values. '
|
||||
'Default is to delete them after the new values are set.'
|
||||
),
|
||||
)
|
||||
parser.add_option(
|
||||
'--overwrite', action='store_true', default=False,
|
||||
help=(
|
||||
'Overwrite any existing git-multimail configuration settings. '
|
||||
'Default is to abort if such settings already exist.'
|
||||
),
|
||||
)
|
||||
|
||||
(options, args) = parser.parse_args(args)
|
||||
|
||||
if args:
|
||||
parser.error('Unexpected arguments: %s' % (' '.join(args),))
|
||||
|
||||
migrate_config(strict=options.strict, retain=options.retain, overwrite=options.overwrite)
|
||||
|
||||
|
||||
main(sys.argv[1:])
|
90
contrib/hooks/multimail/post-receive
Executable file
90
contrib/hooks/multimail/post-receive
Executable file
@ -0,0 +1,90 @@
|
||||
#! /usr/bin/env python2
|
||||
|
||||
"""Example post-receive hook based on git-multimail.
|
||||
|
||||
This script is a simple example of a post-receive hook implemented
|
||||
using git_multimail.py as a Python module. It is intended to be
|
||||
customized before use; see the comments in the script to help you get
|
||||
started.
|
||||
|
||||
It is possible to use git_multimail.py itself as a post-receive or
|
||||
update hook, configured via git config settings and/or command-line
|
||||
parameters. But for more flexibility, it can also be imported as a
|
||||
Python module by a custom post-receive script as done here. The
|
||||
latter has the following advantages:
|
||||
|
||||
* The tool's behavior can be customized using arbitrary Python code,
|
||||
without having to edit git_multimail.py.
|
||||
|
||||
* Configuration settings can be read from other sources; for example,
|
||||
user names and email addresses could be read from LDAP or from a
|
||||
database. Or the settings can even be hardcoded in the importing
|
||||
Python script, if this is preferred.
|
||||
|
||||
This script is a very basic example of how to use git_multimail.py as
|
||||
a module. The comments below explain some of the points at which the
|
||||
script's behavior could be changed or customized.
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# If necessary, add the path to the directory containing
|
||||
# git_multimail.py to the Python path as follows. (This is not
|
||||
# necessary if git_multimail.py is in the same directory as this
|
||||
# script):
|
||||
|
||||
#LIBDIR = 'path/to/directory/containing/module'
|
||||
#sys.path.insert(0, LIBDIR)
|
||||
|
||||
import git_multimail
|
||||
|
||||
|
||||
# It is possible to modify the output templates here; e.g.:
|
||||
|
||||
#git_multimail.FOOTER_TEMPLATE = """\
|
||||
#
|
||||
#-- \n\
|
||||
#This email was generated by the wonderful git-multimail tool.
|
||||
#"""
|
||||
|
||||
|
||||
# Specify which "git config" section contains the configuration for
|
||||
# git-multimail:
|
||||
config = git_multimail.Config('multimailhook')
|
||||
|
||||
|
||||
# Select the type of environment:
|
||||
environment = git_multimail.GenericEnvironment(config=config)
|
||||
#environment = git_multimail.GitoliteEnvironment(config=config)
|
||||
|
||||
|
||||
# Choose the method of sending emails based on the git config:
|
||||
mailer = git_multimail.choose_mailer(config, environment)
|
||||
|
||||
# Alternatively, you may hardcode the mailer using code like one of
|
||||
# the following:
|
||||
|
||||
# Use "/usr/sbin/sendmail -t" to send emails. The envelopesender
|
||||
# argument is optional:
|
||||
#mailer = git_multimail.SendMailer(
|
||||
# command=['/usr/sbin/sendmail', '-t'],
|
||||
# envelopesender='git-repo@example.com',
|
||||
# )
|
||||
|
||||
# Use Python's smtplib to send emails. Both arguments are required.
|
||||
#mailer = git_multimail.SMTPMailer(
|
||||
# envelopesender='git-repo@example.com',
|
||||
# # The smtpserver argument can also include a port number; e.g.,
|
||||
# # smtpserver='mail.example.com:25'
|
||||
# smtpserver='mail.example.com',
|
||||
# )
|
||||
|
||||
# OutputMailer is intended only for testing; it writes the emails to
|
||||
# the specified file stream.
|
||||
#mailer = git_multimail.OutputMailer(sys.stdout)
|
||||
|
||||
|
||||
# Read changes from stdin and send notification emails:
|
||||
git_multimail.run_as_post_receive_hook(environment, mailer)
|
@ -2,10 +2,19 @@
|
||||
#
|
||||
# Copyright (c) 2007 Andy Parkins
|
||||
#
|
||||
# An example hook script to mail out commit update information. This hook
|
||||
# sends emails listing new revisions to the repository introduced by the
|
||||
# change being reported. The rule is that (for branch updates) each commit
|
||||
# will appear on one email and one email only.
|
||||
# An example hook script to mail out commit update information.
|
||||
#
|
||||
# NOTE: This script is no longer under active development. There
|
||||
# is another script, git-multimail, which is more capable and
|
||||
# configurable and is largely backwards-compatible with this script;
|
||||
# please see "contrib/hooks/multimail/". For instructions on how to
|
||||
# migrate from post-receive-email to git-multimail, please see
|
||||
# "README.migrate-from-post-receive-email" in that directory.
|
||||
#
|
||||
# This hook sends emails listing new revisions to the repository
|
||||
# introduced by the change being reported. The rule is that (for
|
||||
# branch updates) each commit will appear on one email and one email
|
||||
# only.
|
||||
#
|
||||
# This hook is stored in the contrib/hooks directory. Your distribution
|
||||
# will have put this somewhere standard. You should make this script
|
||||
|
Loading…
Reference in New Issue
Block a user