#! /usr/bin/env python

__version__ = '1.3.0'

# Copyright (c) 2015 Matthieu Moy and others
# Copyright (c) 2012-2014 Michael Haggerty and others
# Derived from contrib/hooks/post-receive-email, which is
# Copyright (c) 2007 Andy Parkins
# and also includes contributions by other authors.
#
# This file is part of git-multimail.
#
# git-multimail is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License version
# 2 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see
# <http://www.gnu.org/licenses/>.

"""Generate notification emails for pushes to a git repository.

This hook sends emails describing changes introduced by pushes to a
git repository.  For each reference that was changed, it emits one
ReferenceChange email summarizing how the reference was changed,
followed by one Revision email for each new commit that was introduced
by the reference change.

Each commit is announced in exactly one Revision email.  If the same
commit is merged into another branch in the same or a later push, then
the ReferenceChange email will list the commit's SHA1 and its one-line
summary, but no new Revision email will be generated.

This script is designed to be used as a "post-receive" hook in a git
repository (see githooks(5)).  It can also be used as an "update"
script, but this usage is not completely reliable and is deprecated.

To help with debugging, this script accepts a --stdout option, which
causes the emails to be written to standard output rather than sent
using sendmail.

See the accompanying README file for the complete documentation.

"""

import sys
import os
import re
import bisect
import socket
import subprocess
import shlex
import optparse
import smtplib
try:
    import ssl
except ImportError:
    # Python < 2.6 do not have ssl, but that's OK if we don't use it.
    pass
import time
import cgi

PYTHON3 = sys.version_info >= (3, 0)

if sys.version_info <= (2, 5):
    def all(iterable):
        for element in iterable:
            if not element:
                return False
            return True


def is_ascii(s):
    return all(ord(c) < 128 and ord(c) > 0 for c in s)


if PYTHON3:
    def is_string(s):
        return isinstance(s, str)

    def str_to_bytes(s):
        return s.encode(ENCODING)

    def bytes_to_str(s):
        return s.decode(ENCODING)

    unicode = str

    def write_str(f, msg):
        # Try outputing with the default encoding. If it fails,
        # try UTF-8.
        try:
            f.buffer.write(msg.encode(sys.getdefaultencoding()))
        except UnicodeEncodeError:
            f.buffer.write(msg.encode(ENCODING))
else:
    def is_string(s):
        try:
            return isinstance(s, basestring)
        except NameError:  # Silence Pyflakes warning
            raise

    def str_to_bytes(s):
        return s

    def bytes_to_str(s):
        return s

    def write_str(f, msg):
        f.write(msg)

    def next(it):
        return it.next()


try:
    from email.charset import Charset
    from email.utils import make_msgid
    from email.utils import getaddresses
    from email.utils import formataddr
    from email.utils import formatdate
    from email.header import Header
except ImportError:
    # Prior to Python 2.5, the email module used different names:
    from email.Charset import Charset
    from email.Utils import make_msgid
    from email.Utils import getaddresses
    from email.Utils import formataddr
    from email.Utils import formatdate
    from email.Header import Header


DEBUG = False

ZEROS = '0' * 40
LOGBEGIN = '- Log -----------------------------------------------------------------\n'
LOGEND = '-----------------------------------------------------------------------\n'

ADDR_HEADERS = set(['from', 'to', 'cc', 'bcc', 'reply-to', 'sender'])

# It is assumed in many places that the encoding is uniformly UTF-8,
# so changing these constants is unsupported.  But define them here
# anyway, to make it easier to find (at least most of) the places
# where the encoding is important.
(ENCODING, CHARSET) = ('UTF-8', 'utf-8')


REF_CREATED_SUBJECT_TEMPLATE = (
    '%(emailprefix)s%(refname_type)s %(short_refname)s created'
    ' (now %(newrev_short)s)'
    )
REF_UPDATED_SUBJECT_TEMPLATE = (
    '%(emailprefix)s%(refname_type)s %(short_refname)s updated'
    ' (%(oldrev_short)s -> %(newrev_short)s)'
    )
REF_DELETED_SUBJECT_TEMPLATE = (
    '%(emailprefix)s%(refname_type)s %(short_refname)s deleted'
    ' (was %(oldrev_short)s)'
    )

COMBINED_REFCHANGE_REVISION_SUBJECT_TEMPLATE = (
    '%(emailprefix)s%(refname_type)s %(short_refname)s updated: %(oneline)s'
    )

REFCHANGE_HEADER_TEMPLATE = """\
Date: %(send_date)s
To: %(recipients)s
Subject: %(subject)s
MIME-Version: 1.0
Content-Type: text/%(contenttype)s; charset=%(charset)s
Content-Transfer-Encoding: 8bit
Message-ID: %(msgid)s
From: %(fromaddr)s
Reply-To: %(reply_to)s
X-Git-Host: %(fqdn)s
X-Git-Repo: %(repo_shortname)s
X-Git-Refname: %(refname)s
X-Git-Reftype: %(refname_type)s
X-Git-Oldrev: %(oldrev)s
X-Git-Newrev: %(newrev)s
X-Git-NotificationType: ref_changed
X-Git-Multimail-Version: %(multimail_version)s
Auto-Submitted: auto-generated
"""

REFCHANGE_INTRO_TEMPLATE = """\
This is an automated email from the git hooks/post-receive script.

%(pusher)s pushed a change to %(refname_type)s %(short_refname)s
in repository %(repo_shortname)s.

"""


FOOTER_TEMPLATE = """\

-- \n\
To stop receiving notification emails like this one, please contact
%(administrator)s.
"""


REWIND_ONLY_TEMPLATE = """\
This update removed existing revisions from the reference, leaving the
reference pointing at a previous point in the repository history.

 * -- * -- N   %(refname)s (%(newrev_short)s)
            \\
             O -- O -- O   (%(oldrev_short)s)

Any revisions marked "omits" are not gone; other references still
refer to them.  Any revisions marked "discards" are gone forever.
"""


NON_FF_TEMPLATE = """\
This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
%(refname_type)s are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (%(oldrev_short)s)
            \\
             N -- N -- N   %(refname)s (%(newrev_short)s)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omits" are not gone; other references still
refer to them.  Any revisions marked "discards" are gone forever.
"""


NO_NEW_REVISIONS_TEMPLATE = """\
No new revisions were added by this update.
"""


DISCARDED_REVISIONS_TEMPLATE = """\
This change permanently discards the following revisions:
"""


NO_DISCARDED_REVISIONS_TEMPLATE = """\
The revisions that were on this %(refname_type)s are still contained in
other references; therefore, this change does not discard any commits
from the repository.
"""


NEW_REVISIONS_TEMPLATE = """\
The %(tot)s revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "adds" were already present in the repository and have only
been added to this reference.

"""


TAG_CREATED_TEMPLATE = """\
        at  %(newrev_short)-9s (%(newrev_type)s)
"""


TAG_UPDATED_TEMPLATE = """\
*** WARNING: tag %(short_refname)s was modified! ***

      from  %(oldrev_short)-9s (%(oldrev_type)s)
        to  %(newrev_short)-9s (%(newrev_type)s)
"""


TAG_DELETED_TEMPLATE = """\
*** WARNING: tag %(short_refname)s was deleted! ***

"""


# The template used in summary tables.  It looks best if this uses the
# same alignment as TAG_CREATED_TEMPLATE and TAG_UPDATED_TEMPLATE.
BRIEF_SUMMARY_TEMPLATE = """\
%(action)10s  %(rev_short)-9s %(text)s
"""


NON_COMMIT_UPDATE_TEMPLATE = """\
This is an unusual reference change because the reference did not
refer to a commit either before or after the change.  We do not know
how to provide full information about this reference change.
"""


REVISION_HEADER_TEMPLATE = """\
Date: %(send_date)s
To: %(recipients)s
Cc: %(cc_recipients)s
Subject: %(emailprefix)s%(num)02d/%(tot)02d: %(oneline)s
MIME-Version: 1.0
Content-Type: text/%(contenttype)s; charset=%(charset)s
Content-Transfer-Encoding: 8bit
From: %(fromaddr)s
Reply-To: %(reply_to)s
In-Reply-To: %(reply_to_msgid)s
References: %(reply_to_msgid)s
X-Git-Host: %(fqdn)s
X-Git-Repo: %(repo_shortname)s
X-Git-Refname: %(refname)s
X-Git-Reftype: %(refname_type)s
X-Git-Rev: %(rev)s
X-Git-NotificationType: diff
X-Git-Multimail-Version: %(multimail_version)s
Auto-Submitted: auto-generated
"""

REVISION_INTRO_TEMPLATE = """\
This is an automated email from the git hooks/post-receive script.

%(pusher)s pushed a commit to %(refname_type)s %(short_refname)s
in repository %(repo_shortname)s.

"""

LINK_TEXT_TEMPLATE = """\
View the commit online:
%(browse_url)s

"""

LINK_HTML_TEMPLATE = """\
<p><a href="%(browse_url)s">View the commit online</a>.</p>
"""


REVISION_FOOTER_TEMPLATE = FOOTER_TEMPLATE


# Combined, meaning refchange+revision email (for single-commit additions)
COMBINED_HEADER_TEMPLATE = """\
Date: %(send_date)s
To: %(recipients)s
Subject: %(subject)s
MIME-Version: 1.0
Content-Type: text/%(contenttype)s; charset=%(charset)s
Content-Transfer-Encoding: 8bit
Message-ID: %(msgid)s
From: %(fromaddr)s
Reply-To: %(reply_to)s
X-Git-Host: %(fqdn)s
X-Git-Repo: %(repo_shortname)s
X-Git-Refname: %(refname)s
X-Git-Reftype: %(refname_type)s
X-Git-Oldrev: %(oldrev)s
X-Git-Newrev: %(newrev)s
X-Git-Rev: %(rev)s
X-Git-NotificationType: ref_changed_plus_diff
X-Git-Multimail-Version: %(multimail_version)s
Auto-Submitted: auto-generated
"""

COMBINED_INTRO_TEMPLATE = """\
This is an automated email from the git hooks/post-receive script.

%(pusher)s pushed a commit to %(refname_type)s %(short_refname)s
in repository %(repo_shortname)s.

"""

COMBINED_FOOTER_TEMPLATE = FOOTER_TEMPLATE


class CommandError(Exception):
    def __init__(self, cmd, retcode):
        self.cmd = cmd
        self.retcode = retcode
        Exception.__init__(
            self,
            'Command "%s" failed with retcode %s' % (' '.join(cmd), retcode,)
            )


class ConfigurationException(Exception):
    pass


# The "git" program (this could be changed to include a full path):
GIT_EXECUTABLE = 'git'


# How "git" should be invoked (including global arguments), as a list
# of words.  This variable is usually initialized automatically by
# read_git_output() via choose_git_command(), but if a value is set
# here then it will be used unconditionally.
GIT_CMD = None


def choose_git_command():
    """Decide how to invoke git, and record the choice in GIT_CMD."""

    global GIT_CMD

    if GIT_CMD is None:
        try:
            # Check to see whether the "-c" option is accepted (it was
            # only added in Git 1.7.2).  We don't actually use the
            # output of "git --version", though if we needed more
            # specific version information this would be the place to
            # do it.
            cmd = [GIT_EXECUTABLE, '-c', 'foo.bar=baz', '--version']
            read_output(cmd)
            GIT_CMD = [GIT_EXECUTABLE, '-c', 'i18n.logoutputencoding=%s' % (ENCODING,)]
        except CommandError:
            GIT_CMD = [GIT_EXECUTABLE]


def read_git_output(args, input=None, keepends=False, **kw):
    """Read the output of a Git command."""

    if GIT_CMD is None:
        choose_git_command()

    return read_output(GIT_CMD + args, input=input, keepends=keepends, **kw)


def read_output(cmd, input=None, keepends=False, **kw):
    if input:
        stdin = subprocess.PIPE
        input = str_to_bytes(input)
    else:
        stdin = None
    p = subprocess.Popen(
        cmd, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kw
        )
    (out, err) = p.communicate(input)
    out = bytes_to_str(out)
    retcode = p.wait()
    if retcode:
        raise CommandError(cmd, retcode)
    if not keepends:
        out = out.rstrip('\n\r')
    return out


def read_git_lines(args, keepends=False, **kw):
    """Return the lines output by Git command.

    Return as single lines, with newlines stripped off."""

    return read_git_output(args, keepends=True, **kw).splitlines(keepends)


def git_rev_list_ish(cmd, spec, args=None, **kw):
    """Common functionality for invoking a 'git rev-list'-like command.

    Parameters:
      * cmd is the Git command to run, e.g., 'rev-list' or 'log'.
      * spec is a list of revision arguments to pass to the named
        command.  If None, this function returns an empty list.
      * args is a list of extra arguments passed to the named command.
      * All other keyword arguments (if any) are passed to the
        underlying read_git_lines() function.

    Return the output of the Git command in the form of a list, one
    entry per output line.
    """
    if spec is None:
        return []
    if args is None:
        args = []
    args = [cmd, '--stdin'] + args
    spec_stdin = ''.join(s + '\n' for s in spec)
    return read_git_lines(args, input=spec_stdin, **kw)


def git_rev_list(spec, **kw):
    """Run 'git rev-list' with the given list of revision arguments.

    See git_rev_list_ish() for parameter and return value
    documentation.
    """
    return git_rev_list_ish('rev-list', spec, **kw)


def git_log(spec, **kw):
    """Run 'git log' with the given list of revision arguments.

    See git_rev_list_ish() for parameter and return value
    documentation.
    """
    return git_rev_list_ish('log', spec, **kw)


def header_encode(text, header_name=None):
    """Encode and line-wrap the value of an email header field."""

    # Convert to unicode, if required.
    if not isinstance(text, unicode):
        text = unicode(text, 'utf-8')

    if is_ascii(text):
        charset = 'ascii'
    else:
        charset = 'utf-8'

    return Header(text, header_name=header_name, charset=Charset(charset)).encode()


def addr_header_encode(text, header_name=None):
    """Encode and line-wrap the value of an email header field containing
    email addresses."""

    # Convert to unicode, if required.
    if not isinstance(text, unicode):
        text = unicode(text, 'utf-8')

    text = ', '.join(
        formataddr((header_encode(name), emailaddr))
        for name, emailaddr in getaddresses([text])
        )

    if is_ascii(text):
        charset = 'ascii'
    else:
        charset = 'utf-8'

    return Header(text, header_name=header_name, charset=Charset(charset)).encode()


class Config(object):
    def __init__(self, section, git_config=None):
        """Represent a section of the git configuration.

        If git_config is specified, it is passed to "git config" in
        the GIT_CONFIG environment variable, meaning that "git config"
        will read the specified path rather than the Git default
        config paths."""

        self.section = section
        if git_config:
            self.env = os.environ.copy()
            self.env['GIT_CONFIG'] = git_config
        else:
            self.env = None

    @staticmethod
    def _split(s):
        """Split NUL-terminated values."""

        words = s.split('\0')
        assert words[-1] == ''
        return words[:-1]

    @staticmethod
    def add_config_parameters(c):
        """Add configuration parameters to Git.

        c is either an str or a list of str, each element being of the
        form 'var=val' or 'var', with the same syntax and meaning as
        the argument of 'git -c var=val'.
        """
        if isinstance(c, str):
            c = (c,)
        parameters = os.environ.get('GIT_CONFIG_PARAMETERS', '')
        if parameters:
            parameters += ' '
        # git expects GIT_CONFIG_PARAMETERS to be of the form
        #    "'name1=value1' 'name2=value2' 'name3=value3'"
        # including everything inside the double quotes (but not the double
        # quotes themselves).  Spacing is critical.  Also, if a value contains
        # a literal single quote that quote must be represented using the
        # four character sequence: '\''
        parameters += ' '.join("'" + x.replace("'", "'\\''") + "'" for x in c)
        os.environ['GIT_CONFIG_PARAMETERS'] = parameters

    def get(self, name, default=None):
        try:
            values = self._split(read_git_output(
                ['config', '--get', '--null', '%s.%s' % (self.section, name)],
                env=self.env, keepends=True,
                ))
            assert len(values) == 1
            return values[0]
        except CommandError:
            return default

    def get_bool(self, name, default=None):
        try:
            value = read_git_output(
                ['config', '--get', '--bool', '%s.%s' % (self.section, name)],
                env=self.env,
                )
        except CommandError:
            return default
        return value == 'true'

    def get_all(self, name, default=None):
        """Read a (possibly multivalued) setting from the configuration.

        Return the result as a list of values, or default if the name
        is unset."""

        try:
            return self._split(read_git_output(
                ['config', '--get-all', '--null', '%s.%s' % (self.section, name)],
                env=self.env, keepends=True,
                ))
        except CommandError:
            t, e, traceback = sys.exc_info()
            if e.retcode == 1:
                # "the section or key is invalid"; i.e., there is no
                # value for the specified key.
                return default
            else:
                raise

    def set(self, name, value):
        read_git_output(
            ['config', '%s.%s' % (self.section, name), value],
            env=self.env,
            )

    def add(self, name, value):
        read_git_output(
            ['config', '--add', '%s.%s' % (self.section, name), value],
            env=self.env,
            )

    def __contains__(self, name):
        return self.get_all(name, default=None) is not None

    # We don't use this method anymore internally, but keep it here in
    # case somebody is calling it from their own code:
    def has_key(self, name):
        return name in self

    def unset_all(self, name):
        try:
            read_git_output(
                ['config', '--unset-all', '%s.%s' % (self.section, name)],
                env=self.env,
                )
        except CommandError:
            t, e, traceback = sys.exc_info()
            if e.retcode == 5:
                # The name doesn't exist, which is what we wanted anyway...
                pass
            else:
                raise

    def set_recipients(self, name, value):
        self.unset_all(name)
        for pair in getaddresses([value]):
            self.add(name, formataddr(pair))


def generate_summaries(*log_args):
    """Generate a brief summary for each revision requested.

    log_args are strings that will be passed directly to "git log" as
    revision selectors.  Iterate over (sha1_short, subject) for each
    commit specified by log_args (subject is the first line of the
    commit message as a string without EOLs)."""

    cmd = [
        'log', '--abbrev', '--format=%h %s',
        ] + list(log_args) + ['--']
    for line in read_git_lines(cmd):
        yield tuple(line.split(' ', 1))


def limit_lines(lines, max_lines):
    for (index, line) in enumerate(lines):
        if index < max_lines:
            yield line

    if index >= max_lines:
        yield '... %d lines suppressed ...\n' % (index + 1 - max_lines,)


def limit_linelength(lines, max_linelength):
    for line in lines:
        # Don't forget that lines always include a trailing newline.
        if len(line) > max_linelength + 1:
            line = line[:max_linelength - 7] + ' [...]\n'
        yield line


class CommitSet(object):
    """A (constant) set of object names.

    The set should be initialized with full SHA1 object names.  The
    __contains__() method returns True iff its argument is an
    abbreviation of any the names in the set."""

    def __init__(self, names):
        self._names = sorted(names)

    def __len__(self):
        return len(self._names)

    def __contains__(self, sha1_abbrev):
        """Return True iff this set contains sha1_abbrev (which might be abbreviated)."""

        i = bisect.bisect_left(self._names, sha1_abbrev)
        return i < len(self) and self._names[i].startswith(sha1_abbrev)


class GitObject(object):
    def __init__(self, sha1, type=None):
        if sha1 == ZEROS:
            self.sha1 = self.type = self.commit_sha1 = None
        else:
            self.sha1 = sha1
            self.type = type or read_git_output(['cat-file', '-t', self.sha1])

            if self.type == 'commit':
                self.commit_sha1 = self.sha1
            elif self.type == 'tag':
                try:
                    self.commit_sha1 = read_git_output(
                        ['rev-parse', '--verify', '%s^0' % (self.sha1,)]
                        )
                except CommandError:
                    # Cannot deref tag to determine commit_sha1
                    self.commit_sha1 = None
            else:
                self.commit_sha1 = None

        self.short = read_git_output(['rev-parse', '--short', sha1])

    def get_summary(self):
        """Return (sha1_short, subject) for this commit."""

        if not self.sha1:
            raise ValueError('Empty commit has no summary')

        return next(iter(generate_summaries('--no-walk', self.sha1)))

    def __eq__(self, other):
        return isinstance(other, GitObject) and self.sha1 == other.sha1

    def __hash__(self):
        return hash(self.sha1)

    def __nonzero__(self):
        return bool(self.sha1)

    def __bool__(self):
        """Python 2 backward compatibility"""
        return self.__nonzero__()

    def __str__(self):
        return self.sha1 or ZEROS


class Change(object):
    """A Change that has been made to the Git repository.

    Abstract class from which both Revisions and ReferenceChanges are
    derived.  A Change knows how to generate a notification email
    describing itself."""

    def __init__(self, environment):
        self.environment = environment
        self._values = None
        self._contains_html_diff = False

    def _contains_diff(self):
        # We do contain a diff, should it be rendered in HTML?
        if self.environment.commit_email_format == "html":
            self._contains_html_diff = True

    def _compute_values(self):
        """Return a dictionary {keyword: expansion} for this Change.

        Derived classes overload this method to add more entries to
        the return value.  This method is used internally by
        get_values().  The return value should always be a new
        dictionary."""

        values = self.environment.get_values()
        fromaddr = self.environment.get_fromaddr(change=self)
        if fromaddr is not None:
            values['fromaddr'] = fromaddr
        values['multimail_version'] = get_version()
        return values

    # Aliases usable in template strings. Tuple of pairs (destination,
    # source).
    VALUES_ALIAS = (
        ("id", "newrev"),
        )

    def get_values(self, **extra_values):
        """Return a dictionary {keyword: expansion} for this Change.

        Return a dictionary mapping keywords to the values that they
        should be expanded to for this Change (used when interpolating
        template strings).  If any keyword arguments are supplied, add
        those to the return value as well.  The return value is always
        a new dictionary."""

        if self._values is None:
            self._values = self._compute_values()

        values = self._values.copy()
        if extra_values:
            values.update(extra_values)

        for alias, val in self.VALUES_ALIAS:
            values[alias] = values[val]
        return values

    def expand(self, template, **extra_values):
        """Expand template.

        Expand the template (which should be a string) using string
        interpolation of the values for this Change.  If any keyword
        arguments are provided, also include those in the keywords
        available for interpolation."""

        return template % self.get_values(**extra_values)

    def expand_lines(self, template, html_escape_val=False, **extra_values):
        """Break template into lines and expand each line."""

        values = self.get_values(**extra_values)
        if html_escape_val:
            for k in values:
                if is_string(values[k]):
                    values[k] = cgi.escape(values[k], True)
        for line in template.splitlines(True):
            yield line % values

    def expand_header_lines(self, template, **extra_values):
        """Break template into lines and expand each line as an RFC 2822 header.

        Encode values and split up lines that are too long.  Silently
        skip lines that contain references to unknown variables."""

        values = self.get_values(**extra_values)
        if self._contains_html_diff:
            self._content_type = 'html'
        else:
            self._content_type = 'plain'
        values['contenttype'] = self._content_type

        for line in template.splitlines():
            (name, value) = line.split(': ', 1)

            try:
                value = value % values
            except KeyError:
                t, e, traceback = sys.exc_info()
                if DEBUG:
                    self.environment.log_warning(
                        'Warning: unknown variable %r in the following line; line skipped:\n'
                        '    %s\n'
                        % (e.args[0], line,)
                        )
            else:
                if name.lower() in ADDR_HEADERS:
                    value = addr_header_encode(value, name)
                else:
                    value = header_encode(value, name)
                for splitline in ('%s: %s\n' % (name, value)).splitlines(True):
                    yield splitline

    def generate_email_header(self):
        """Generate the RFC 2822 email headers for this Change, a line at a time.

        The output should not include the trailing blank line."""

        raise NotImplementedError()

    def generate_browse_link(self, base_url):
        """Generate a link to an online repository browser."""
        return iter(())

    def generate_email_intro(self, html_escape_val=False):
        """Generate the email intro for this Change, a line at a time.

        The output will be used as the standard boilerplate at the top
        of the email body."""

        raise NotImplementedError()

    def generate_email_body(self):
        """Generate the main part of the email body, a line at a time.

        The text in the body might be truncated after a specified
        number of lines (see multimailhook.emailmaxlines)."""

        raise NotImplementedError()

    def generate_email_footer(self, html_escape_val):
        """Generate the footer of the email, a line at a time.

        The footer is always included, irrespective of
        multimailhook.emailmaxlines."""

        raise NotImplementedError()

    def _wrap_for_html(self, lines):
        """Wrap the lines in HTML <pre> tag when using HTML format.

        Escape special HTML characters and add <pre> and </pre> tags around
        the given lines if we should be generating HTML as indicated by
        self._contains_html_diff being set to true.
        """
        if self._contains_html_diff:
            yield "<pre style='margin:0'>\n"

            for line in lines:
                yield cgi.escape(line)

            yield '</pre>\n'
        else:
            for line in lines:
                yield line

    def generate_email(self, push, body_filter=None, extra_header_values={}):
        """Generate an email describing this change.

        Iterate over the lines (including the header lines) of an
        email describing this change.  If body_filter is not None,
        then use it to filter the lines that are intended for the
        email body.

        The extra_header_values field is received as a dict and not as
        **kwargs, to allow passing other keyword arguments in the
        future (e.g. passing extra values to generate_email_intro()"""

        for line in self.generate_email_header(**extra_header_values):
            yield line
        yield '\n'
        html_escape_val = (self.environment.html_in_intro and
                           self._contains_html_diff)
        intro = self.generate_email_intro(html_escape_val)
        if not self.environment.html_in_intro:
            intro = self._wrap_for_html(intro)
        for line in intro:
            yield line

        if self.environment.commitBrowseURL:
            for line in self.generate_browse_link(self.environment.commitBrowseURL):
                yield line

        body = self.generate_email_body(push)
        if body_filter is not None:
            body = body_filter(body)

        diff_started = False
        if self._contains_html_diff:
            # "white-space: pre" is the default, but we need to
            # specify it again in case the message is viewed in a
            # webmail which wraps it in an element setting white-space
            # to something else (Zimbra does this and sets
            # white-space: pre-line).
            yield '<pre style="white-space: pre; background: #F8F8F8">'
        for line in body:
            if self._contains_html_diff:
                # This is very, very naive. It would be much better to really
                # parse the diff, i.e. look at how many lines do we have in
                # the hunk headers instead of blindly highlighting everything
                # that looks like it might be part of a diff.
                bgcolor = ''
                fgcolor = ''
                if line.startswith('--- a/'):
                    diff_started = True
                    bgcolor = 'e0e0ff'
                elif line.startswith('diff ') or line.startswith('index '):
                    diff_started = True
                    fgcolor = '808080'
                elif diff_started:
                    if line.startswith('+++ '):
                        bgcolor = 'e0e0ff'
                    elif line.startswith('@@'):
                        bgcolor = 'e0e0e0'
                    elif line.startswith('+'):
                        bgcolor = 'e0ffe0'
                    elif line.startswith('-'):
                        bgcolor = 'ffe0e0'
                elif line.startswith('commit '):
                    fgcolor = '808000'
                elif line.startswith('    '):
                    fgcolor = '404040'

                # Chop the trailing LF, we don't want it inside <pre>.
                line = cgi.escape(line[:-1])

                if bgcolor or fgcolor:
                    style = 'display:block; white-space:pre;'
                    if bgcolor:
                        style += 'background:#' + bgcolor + ';'
                    if fgcolor:
                        style += 'color:#' + fgcolor + ';'
                    # Use a <span style='display:block> to color the
                    # whole line. The newline must be inside the span
                    # to display properly both in Firefox and in
                    # text-based browser.
                    line = "<span style='%s'>%s\n</span>" % (style, line)
                else:
                    line = line + '\n'

            yield line
        if self._contains_html_diff:
            yield '</pre>'
        html_escape_val = (self.environment.html_in_footer and
                           self._contains_html_diff)
        footer = self.generate_email_footer(html_escape_val)
        if not self.environment.html_in_footer:
            footer = self._wrap_for_html(footer)
        for line in footer:
            yield line

    def get_alt_fromaddr(self):
        return None


class Revision(Change):
    """A Change consisting of a single git commit."""

    CC_RE = re.compile(r'^\s*C[Cc]:\s*(?P<to>[^#]+@[^\s#]*)\s*(#.*)?$')

    def __init__(self, reference_change, rev, num, tot):
        Change.__init__(self, reference_change.environment)
        self.reference_change = reference_change
        self.rev = rev
        self.change_type = self.reference_change.change_type
        self.refname = self.reference_change.refname
        self.num = num
        self.tot = tot
        self.author = read_git_output(['log', '--no-walk', '--format=%aN <%aE>', self.rev.sha1])
        self.recipients = self.environment.get_revision_recipients(self)

        self.cc_recipients = ''
        if self.environment.get_scancommitforcc():
            self.cc_recipients = ', '.join(to.strip() for to in self._cc_recipients())
            if self.cc_recipients:
                self.environment.log_msg(
                    'Add %s to CC for %s\n' % (self.cc_recipients, self.rev.sha1))

    def _cc_recipients(self):
        cc_recipients = []
        message = read_git_output(['log', '--no-walk', '--format=%b', self.rev.sha1])
        lines = message.strip().split('\n')
        for line in lines:
            m = re.match(self.CC_RE, line)
            if m:
                cc_recipients.append(m.group('to'))

        return cc_recipients

    def _compute_values(self):
        values = Change._compute_values(self)

        oneline = read_git_output(
            ['log', '--format=%s', '--no-walk', self.rev.sha1]
            )

        values['rev'] = self.rev.sha1
        values['rev_short'] = self.rev.short
        values['change_type'] = self.change_type
        values['refname'] = self.refname
        values['newrev'] = self.rev.sha1
        values['short_refname'] = self.reference_change.short_refname
        values['refname_type'] = self.reference_change.refname_type
        values['reply_to_msgid'] = self.reference_change.msgid
        values['num'] = self.num
        values['tot'] = self.tot
        values['recipients'] = self.recipients
        if self.cc_recipients:
            values['cc_recipients'] = self.cc_recipients
        values['oneline'] = oneline
        values['author'] = self.author

        reply_to = self.environment.get_reply_to_commit(self)
        if reply_to:
            values['reply_to'] = reply_to

        return values

    def generate_email_header(self, **extra_values):
        for line in self.expand_header_lines(
                REVISION_HEADER_TEMPLATE, **extra_values
                ):
            yield line

    def generate_browse_link(self, base_url):
        if '%(' not in base_url:
            base_url += '%(id)s'
        url = "".join(self.expand_lines(base_url))
        if self._content_type == 'html':
            for line in self.expand_lines(LINK_HTML_TEMPLATE,
                                          html_escape_val=True,
                                          browse_url=url):
                yield line
        elif self._content_type == 'plain':
            for line in self.expand_lines(LINK_TEXT_TEMPLATE,
                                          html_escape_val=False,
                                          browse_url=url):
                yield line
        else:
            raise NotImplementedError("Content-type %s unsupported. Please report it as a bug.")

    def generate_email_intro(self, html_escape_val=False):
        for line in self.expand_lines(REVISION_INTRO_TEMPLATE,
                                      html_escape_val=html_escape_val):
            yield line

    def generate_email_body(self, push):
        """Show this revision."""

        for line in read_git_lines(
                ['log'] + self.environment.commitlogopts + ['-1', self.rev.sha1],
                keepends=True,
                ):
            if line.startswith('Date:   ') and self.environment.date_substitute:
                yield self.environment.date_substitute + line[len('Date:   '):]
            else:
                yield line

    def generate_email_footer(self, html_escape_val):
        return self.expand_lines(REVISION_FOOTER_TEMPLATE,
                                 html_escape_val=html_escape_val)

    def generate_email(self, push, body_filter=None, extra_header_values={}):
        self._contains_diff()
        return Change.generate_email(self, push, body_filter, extra_header_values)

    def get_alt_fromaddr(self):
        return self.environment.from_commit


class ReferenceChange(Change):
    """A Change to a Git reference.

    An abstract class representing a create, update, or delete of a
    Git reference.  Derived classes handle specific types of reference
    (e.g., tags vs. branches).  These classes generate the main
    reference change email summarizing the reference change and
    whether it caused any any commits to be added or removed.

    ReferenceChange objects are usually created using the static
    create() method, which has the logic to decide which derived class
    to instantiate."""

    REF_RE = re.compile(r'^refs\/(?P<area>[^\/]+)\/(?P<shortname>.*)$')

    @staticmethod
    def create(environment, oldrev, newrev, refname):
        """Return a ReferenceChange object representing the change.

        Return an object that represents the type of change that is being
        made. oldrev and newrev should be SHA1s or ZEROS."""

        old = GitObject(oldrev)
        new = GitObject(newrev)
        rev = new or old

        # The revision type tells us what type the commit is, combined with
        # the location of the ref we can decide between
        #  - working branch
        #  - tracking branch
        #  - unannotated tag
        #  - annotated tag
        m = ReferenceChange.REF_RE.match(refname)
        if m:
            area = m.group('area')
            short_refname = m.group('shortname')
        else:
            area = ''
            short_refname = refname

        if rev.type == 'tag':
            # Annotated tag:
            klass = AnnotatedTagChange
        elif rev.type == 'commit':
            if area == 'tags':
                # Non-annotated tag:
                klass = NonAnnotatedTagChange
            elif area == 'heads':
                # Branch:
                klass = BranchChange
            elif area == 'remotes':
                # Tracking branch:
                environment.log_warning(
                    '*** Push-update of tracking branch %r\n'
                    '***  - incomplete email generated.\n'
                    % (refname,)
                    )
                klass = OtherReferenceChange
            else:
                # Some other reference namespace:
                environment.log_warning(
                    '*** Push-update of strange reference %r\n'
                    '***  - incomplete email generated.\n'
                    % (refname,)
                    )
                klass = OtherReferenceChange
        else:
            # Anything else (is there anything else?)
            environment.log_warning(
                '*** Unknown type of update to %r (%s)\n'
                '***  - incomplete email generated.\n'
                % (refname, rev.type,)
                )
            klass = OtherReferenceChange

        return klass(
            environment,
            refname=refname, short_refname=short_refname,
            old=old, new=new, rev=rev,
            )

    def __init__(self, environment, refname, short_refname, old, new, rev):
        Change.__init__(self, environment)
        self.change_type = {
            (False, True): 'create',
            (True, True): 'update',
            (True, False): 'delete',
            }[bool(old), bool(new)]
        self.refname = refname
        self.short_refname = short_refname
        self.old = old
        self.new = new
        self.rev = rev
        self.msgid = make_msgid()
        self.diffopts = environment.diffopts
        self.graphopts = environment.graphopts
        self.logopts = environment.logopts
        self.commitlogopts = environment.commitlogopts
        self.showgraph = environment.refchange_showgraph
        self.showlog = environment.refchange_showlog

        self.header_template = REFCHANGE_HEADER_TEMPLATE
        self.intro_template = REFCHANGE_INTRO_TEMPLATE
        self.footer_template = FOOTER_TEMPLATE

    def _compute_values(self):
        values = Change._compute_values(self)

        values['change_type'] = self.change_type
        values['refname_type'] = self.refname_type
        values['refname'] = self.refname
        values['short_refname'] = self.short_refname
        values['msgid'] = self.msgid
        values['recipients'] = self.recipients
        values['oldrev'] = str(self.old)
        values['oldrev_short'] = self.old.short
        values['newrev'] = str(self.new)
        values['newrev_short'] = self.new.short

        if self.old:
            values['oldrev_type'] = self.old.type
        if self.new:
            values['newrev_type'] = self.new.type

        reply_to = self.environment.get_reply_to_refchange(self)
        if reply_to:
            values['reply_to'] = reply_to

        return values

    def send_single_combined_email(self, known_added_sha1s):
        """Determine if a combined refchange/revision email should be sent

        If there is only a single new (non-merge) commit added by a
        change, it is useful to combine the ReferenceChange and
        Revision emails into one.  In such a case, return the single
        revision; otherwise, return None.

        This method is overridden in BranchChange."""

        return None

    def generate_combined_email(self, push, revision, body_filter=None, extra_header_values={}):
        """Generate an email describing this change AND specified revision.

        Iterate over the lines (including the header lines) of an
        email describing this change.  If body_filter is not None,
        then use it to filter the lines that are intended for the
        email body.

        The extra_header_values field is received as a dict and not as
        **kwargs, to allow passing other keyword arguments in the
        future (e.g. passing extra values to generate_email_intro()

        This method is overridden in BranchChange."""

        raise NotImplementedError

    def get_subject(self):
        template = {
            'create': REF_CREATED_SUBJECT_TEMPLATE,
            'update': REF_UPDATED_SUBJECT_TEMPLATE,
            'delete': REF_DELETED_SUBJECT_TEMPLATE,
            }[self.change_type]
        return self.expand(template)

    def generate_email_header(self, **extra_values):
        if 'subject' not in extra_values:
            extra_values['subject'] = self.get_subject()

        for line in self.expand_header_lines(
                self.header_template, **extra_values
                ):
            yield line

    def generate_email_intro(self, html_escape_val=False):
        for line in self.expand_lines(self.intro_template,
                                      html_escape_val=html_escape_val):
            yield line

    def generate_email_body(self, push):
        """Call the appropriate body-generation routine.

        Call one of generate_create_summary() /
        generate_update_summary() / generate_delete_summary()."""

        change_summary = {
            'create': self.generate_create_summary,
            'delete': self.generate_delete_summary,
            'update': self.generate_update_summary,
            }[self.change_type](push)
        for line in change_summary:
            yield line

        for line in self.generate_revision_change_summary(push):
            yield line

    def generate_email_footer(self, html_escape_val):
        return self.expand_lines(self.footer_template,
                                 html_escape_val=html_escape_val)

    def generate_revision_change_graph(self, push):
        if self.showgraph:
            args = ['--graph'] + self.graphopts
            for newold in ('new', 'old'):
                has_newold = False
                spec = push.get_commits_spec(newold, self)
                for line in git_log(spec, args=args, keepends=True):
                    if not has_newold:
                        has_newold = True
                        yield '\n'
                        yield 'Graph of %s commits:\n\n' % (
                            {'new': 'new', 'old': 'discarded'}[newold],)
                    yield '  ' + line
                if has_newold:
                    yield '\n'

    def generate_revision_change_log(self, new_commits_list):
        if self.showlog:
            yield '\n'
            yield 'Detailed log of new commits:\n\n'
            for line in read_git_lines(
                    ['log', '--no-walk'] +
                    self.logopts +
                    new_commits_list +
                    ['--'],
                    keepends=True,
                    ):
                yield line

    def generate_new_revision_summary(self, tot, new_commits_list, push):
        for line in self.expand_lines(NEW_REVISIONS_TEMPLATE, tot=tot):
            yield line
        for line in self.generate_revision_change_graph(push):
            yield line
        for line in self.generate_revision_change_log(new_commits_list):
            yield line

    def generate_revision_change_summary(self, push):
        """Generate a summary of the revisions added/removed by this change."""

        if self.new.commit_sha1 and not self.old.commit_sha1:
            # A new reference was created.  List the new revisions
            # brought by the new reference (i.e., those revisions that
            # were not in the repository before this reference
            # change).
            sha1s = list(push.get_new_commits(self))
            sha1s.reverse()
            tot = len(sha1s)
            new_revisions = [
                Revision(self, GitObject(sha1), num=i + 1, tot=tot)
                for (i, sha1) in enumerate(sha1s)
                ]

            if new_revisions:
                yield self.expand('This %(refname_type)s includes the following new commits:\n')
                yield '\n'
                for r in new_revisions:
                    (sha1, subject) = r.rev.get_summary()
                    yield r.expand(
                        BRIEF_SUMMARY_TEMPLATE, action='new', text=subject,
                        )
                yield '\n'
                for line in self.generate_new_revision_summary(
                        tot, [r.rev.sha1 for r in new_revisions], push):
                    yield line
            else:
                for line in self.expand_lines(NO_NEW_REVISIONS_TEMPLATE):
                    yield line

        elif self.new.commit_sha1 and self.old.commit_sha1:
            # A reference was changed to point at a different commit.
            # List the revisions that were removed and/or added *from
            # that reference* by this reference change, along with a
            # diff between the trees for its old and new values.

            # List of the revisions that were added to the branch by
            # this update.  Note this list can include revisions that
            # have already had notification emails; we want such
            # revisions in the summary even though we will not send
            # new notification emails for them.
            adds = list(generate_summaries(
                '--topo-order', '--reverse', '%s..%s'
                % (self.old.commit_sha1, self.new.commit_sha1,)
                ))

            # List of the revisions that were removed from the branch
            # by this update.  This will be empty except for
            # non-fast-forward updates.
            discards = list(generate_summaries(
                '%s..%s' % (self.new.commit_sha1, self.old.commit_sha1,)
                ))

            if adds:
                new_commits_list = push.get_new_commits(self)
            else:
                new_commits_list = []
            new_commits = CommitSet(new_commits_list)

            if discards:
                discarded_commits = CommitSet(push.get_discarded_commits(self))
            else:
                discarded_commits = CommitSet([])

            if discards and adds:
                for (sha1, subject) in discards:
                    if sha1 in discarded_commits:
                        action = 'discards'
                    else:
                        action = 'omits'
                    yield self.expand(
                        BRIEF_SUMMARY_TEMPLATE, action=action,
                        rev_short=sha1, text=subject,
                        )
                for (sha1, subject) in adds:
                    if sha1 in new_commits:
                        action = 'new'
                    else:
                        action = 'adds'
                    yield self.expand(
                        BRIEF_SUMMARY_TEMPLATE, action=action,
                        rev_short=sha1, text=subject,
                        )
                yield '\n'
                for line in self.expand_lines(NON_FF_TEMPLATE):
                    yield line

            elif discards:
                for (sha1, subject) in discards:
                    if sha1 in discarded_commits:
                        action = 'discards'
                    else:
                        action = 'omits'
                    yield self.expand(
                        BRIEF_SUMMARY_TEMPLATE, action=action,
                        rev_short=sha1, text=subject,
                        )
                yield '\n'
                for line in self.expand_lines(REWIND_ONLY_TEMPLATE):
                    yield line

            elif adds:
                (sha1, subject) = self.old.get_summary()
                yield self.expand(
                    BRIEF_SUMMARY_TEMPLATE, action='from',
                    rev_short=sha1, text=subject,
                    )
                for (sha1, subject) in adds:
                    if sha1 in new_commits:
                        action = 'new'
                    else:
                        action = 'adds'
                    yield self.expand(
                        BRIEF_SUMMARY_TEMPLATE, action=action,
                        rev_short=sha1, text=subject,
                        )

            yield '\n'

            if new_commits:
                for line in self.generate_new_revision_summary(
                        len(new_commits), new_commits_list, push):
                    yield line
            else:
                for line in self.expand_lines(NO_NEW_REVISIONS_TEMPLATE):
                    yield line
                for line in self.generate_revision_change_graph(push):
                    yield line

            # The diffstat is shown from the old revision to the new
            # revision.  This is to show the truth of what happened in
            # this change.  There's no point showing the stat from the
            # base to the new revision because the base is effectively a
            # random revision at this point - the user will be interested
            # in what this revision changed - including the undoing of
            # previous revisions in the case of non-fast-forward updates.
            yield '\n'
            yield 'Summary of changes:\n'
            for line in read_git_lines(
                    ['diff-tree'] +
                    self.diffopts +
                    ['%s..%s' % (self.old.commit_sha1, self.new.commit_sha1,)],
                    keepends=True,
                    ):
                yield line

        elif self.old.commit_sha1 and not self.new.commit_sha1:
            # A reference was deleted.  List the revisions that were
            # removed from the repository by this reference change.

            sha1s = list(push.get_discarded_commits(self))
            tot = len(sha1s)
            discarded_revisions = [
                Revision(self, GitObject(sha1), num=i + 1, tot=tot)
                for (i, sha1) in enumerate(sha1s)
                ]

            if discarded_revisions:
                for line in self.expand_lines(DISCARDED_REVISIONS_TEMPLATE):
                    yield line
                yield '\n'
                for r in discarded_revisions:
                    (sha1, subject) = r.rev.get_summary()
                    yield r.expand(
                        BRIEF_SUMMARY_TEMPLATE, action='discards', text=subject,
                        )
                for line in self.generate_revision_change_graph(push):
                    yield line
            else:
                for line in self.expand_lines(NO_DISCARDED_REVISIONS_TEMPLATE):
                    yield line

        elif not self.old.commit_sha1 and not self.new.commit_sha1:
            for line in self.expand_lines(NON_COMMIT_UPDATE_TEMPLATE):
                yield line

    def generate_create_summary(self, push):
        """Called for the creation of a reference."""

        # This is a new reference and so oldrev is not valid
        (sha1, subject) = self.new.get_summary()
        yield self.expand(
            BRIEF_SUMMARY_TEMPLATE, action='at',
            rev_short=sha1, text=subject,
            )
        yield '\n'

    def generate_update_summary(self, push):
        """Called for the change of a pre-existing branch."""

        return iter([])

    def generate_delete_summary(self, push):
        """Called for the deletion of any type of reference."""

        (sha1, subject) = self.old.get_summary()
        yield self.expand(
            BRIEF_SUMMARY_TEMPLATE, action='was',
            rev_short=sha1, text=subject,
            )
        yield '\n'

    def get_alt_fromaddr(self):
        return self.environment.from_refchange


class BranchChange(ReferenceChange):
    refname_type = 'branch'

    def __init__(self, environment, refname, short_refname, old, new, rev):
        ReferenceChange.__init__(
            self, environment,
            refname=refname, short_refname=short_refname,
            old=old, new=new, rev=rev,
            )
        self.recipients = environment.get_refchange_recipients(self)
        self._single_revision = None

    def send_single_combined_email(self, known_added_sha1s):
        if not self.environment.combine_when_single_commit:
            return None

        # In the sadly-all-too-frequent usecase of people pushing only
        # one of their commits at a time to a repository, users feel
        # the reference change summary emails are noise rather than
        # important signal.  This is because, in this particular
        # usecase, there is a reference change summary email for each
        # new commit, and all these summaries do is point out that
        # there is one new commit (which can readily be inferred by
        # the existence of the individual revision email that is also
        # sent).  In such cases, our users prefer there to be a combined
        # reference change summary/new revision email.
        #
        # So, if the change is an update and it doesn't discard any
        # commits, and it adds exactly one non-merge commit (gerrit
        # forces a workflow where every commit is individually merged
        # and the git-multimail hook fired off for just this one
        # change), then we send a combined refchange/revision email.
        try:
            # If this change is a reference update that doesn't discard
            # any commits...
            if self.change_type != 'update':
                return None

            if read_git_lines(
                    ['merge-base', self.old.sha1, self.new.sha1]
                    ) != [self.old.sha1]:
                return None

            # Check if this update introduced exactly one non-merge
            # commit:

            def split_line(line):
                """Split line into (sha1, [parent,...])."""

                words = line.split()
                return (words[0], words[1:])

            # Get the new commits introduced by the push as a list of
            # (sha1, [parent,...])
            new_commits = [
                split_line(line)
                for line in read_git_lines(
                    [
                        'log', '-3', '--format=%H %P',
                        '%s..%s' % (self.old.sha1, self.new.sha1),
                        ]
                    )
                ]

            if not new_commits:
                return None

            # If the newest commit is a merge, save it for a later check
            # but otherwise ignore it
            merge = None
            tot = len(new_commits)
            if len(new_commits[0][1]) > 1:
                merge = new_commits[0][0]
                del new_commits[0]

            # Our primary check: we can't combine if more than one commit
            # is introduced.  We also currently only combine if the new
            # commit is a non-merge commit, though it may make sense to
            # combine if it is a merge as well.
            if not (
                    len(new_commits) == 1 and
                    len(new_commits[0][1]) == 1 and
                    new_commits[0][0] in known_added_sha1s
                    ):
                return None

            # We do not want to combine revision and refchange emails if
            # those go to separate locations.
            rev = Revision(self, GitObject(new_commits[0][0]), 1, tot)
            if rev.recipients != self.recipients:
                return None

            # We ignored the newest commit if it was just a merge of the one
            # commit being introduced.  But we don't want to ignore that
            # merge commit it it involved conflict resolutions.  Check that.
            if merge and merge != read_git_output(['diff-tree', '--cc', merge]):
                return None

            # We can combine the refchange and one new revision emails
            # into one.  Return the Revision that a combined email should
            # be sent about.
            return rev
        except CommandError:
            # Cannot determine number of commits in old..new or new..old;
            # don't combine reference/revision emails:
            return None

    def generate_combined_email(self, push, revision, body_filter=None, extra_header_values={}):
        values = revision.get_values()
        if extra_header_values:
            values.update(extra_header_values)
        if 'subject' not in extra_header_values:
            values['subject'] = self.expand(COMBINED_REFCHANGE_REVISION_SUBJECT_TEMPLATE, **values)

        self._single_revision = revision
        self._contains_diff()
        self.header_template = COMBINED_HEADER_TEMPLATE
        self.intro_template = COMBINED_INTRO_TEMPLATE
        self.footer_template = COMBINED_FOOTER_TEMPLATE
        for line in self.generate_email(push, body_filter, values):
            yield line

    def generate_email_body(self, push):
        '''Call the appropriate body generation routine.

        If this is a combined refchange/revision email, the special logic
        for handling this combined email comes from this function.  For
        other cases, we just use the normal handling.'''

        # If self._single_revision isn't set; don't override
        if not self._single_revision:
            for line in super(BranchChange, self).generate_email_body(push):
                yield line
            return

        # This is a combined refchange/revision email; we first provide
        # some info from the refchange portion, and then call the revision
        # generate_email_body function to handle the revision portion.
        adds = list(generate_summaries(
            '--topo-order', '--reverse', '%s..%s'
            % (self.old.commit_sha1, self.new.commit_sha1,)
            ))

        yield self.expand("The following commit(s) were added to %(refname)s by this push:\n")
        for (sha1, subject) in adds:
            yield self.expand(
                BRIEF_SUMMARY_TEMPLATE, action='new',
                rev_short=sha1, text=subject,
                )

        yield self._single_revision.rev.short + " is described below\n"
        yield '\n'

        for line in self._single_revision.generate_email_body(push):
            yield line


class AnnotatedTagChange(ReferenceChange):
    refname_type = 'annotated tag'

    def __init__(self, environment, refname, short_refname, old, new, rev):
        ReferenceChange.__init__(
            self, environment,
            refname=refname, short_refname=short_refname,
            old=old, new=new, rev=rev,
            )
        self.recipients = environment.get_announce_recipients(self)
        self.show_shortlog = environment.announce_show_shortlog

    ANNOTATED_TAG_FORMAT = (
        '%(*objectname)\n'
        '%(*objecttype)\n'
        '%(taggername)\n'
        '%(taggerdate)'
        )

    def describe_tag(self, push):
        """Describe the new value of an annotated tag."""

        # Use git for-each-ref to pull out the individual fields from
        # the tag
        [tagobject, tagtype, tagger, tagged] = read_git_lines(
            ['for-each-ref', '--format=%s' % (self.ANNOTATED_TAG_FORMAT,), self.refname],
            )

        yield self.expand(
            BRIEF_SUMMARY_TEMPLATE, action='tagging',
            rev_short=tagobject, text='(%s)' % (tagtype,),
            )
        if tagtype == 'commit':
            # If the tagged object is a commit, then we assume this is a
            # release, and so we calculate which tag this tag is
            # replacing
            try:
                prevtag = read_git_output(['describe', '--abbrev=0', '%s^' % (self.new,)])
            except CommandError:
                prevtag = None
            if prevtag:
                yield '  replaces  %s\n' % (prevtag,)
        else:
            prevtag = None
            yield '    length  %s bytes\n' % (read_git_output(['cat-file', '-s', tagobject]),)

        yield ' tagged by  %s\n' % (tagger,)
        yield '        on  %s\n' % (tagged,)
        yield '\n'

        # Show the content of the tag message; this might contain a
        # change log or release notes so is worth displaying.
        yield LOGBEGIN
        contents = list(read_git_lines(['cat-file', 'tag', self.new.sha1], keepends=True))
        contents = contents[contents.index('\n') + 1:]
        if contents and contents[-1][-1:] != '\n':
            contents.append('\n')
        for line in contents:
            yield line

        if self.show_shortlog and tagtype == 'commit':
            # Only commit tags make sense to have rev-list operations
            # performed on them
            yield '\n'
            if prevtag:
                # Show changes since the previous release
                revlist = read_git_output(
                    ['rev-list', '--pretty=short', '%s..%s' % (prevtag, self.new,)],
                    keepends=True,
                    )
            else:
                # No previous tag, show all the changes since time
                # began
                revlist = read_git_output(
                    ['rev-list', '--pretty=short', '%s' % (self.new,)],
                    keepends=True,
                    )
            for line in read_git_lines(['shortlog'], input=revlist, keepends=True):
                yield line

        yield LOGEND
        yield '\n'

    def generate_create_summary(self, push):
        """Called for the creation of an annotated tag."""

        for line in self.expand_lines(TAG_CREATED_TEMPLATE):
            yield line

        for line in self.describe_tag(push):
            yield line

    def generate_update_summary(self, push):
        """Called for the update of an annotated tag.

        This is probably a rare event and may not even be allowed."""

        for line in self.expand_lines(TAG_UPDATED_TEMPLATE):
            yield line

        for line in self.describe_tag(push):
            yield line

    def generate_delete_summary(self, push):
        """Called when a non-annotated reference is updated."""

        for line in self.expand_lines(TAG_DELETED_TEMPLATE):
            yield line

        yield self.expand('   tag was  %(oldrev_short)s\n')
        yield '\n'


class NonAnnotatedTagChange(ReferenceChange):
    refname_type = 'tag'

    def __init__(self, environment, refname, short_refname, old, new, rev):
        ReferenceChange.__init__(
            self, environment,
            refname=refname, short_refname=short_refname,
            old=old, new=new, rev=rev,
            )
        self.recipients = environment.get_refchange_recipients(self)

    def generate_create_summary(self, push):
        """Called for the creation of an annotated tag."""

        for line in self.expand_lines(TAG_CREATED_TEMPLATE):
            yield line

    def generate_update_summary(self, push):
        """Called when a non-annotated reference is updated."""

        for line in self.expand_lines(TAG_UPDATED_TEMPLATE):
            yield line

    def generate_delete_summary(self, push):
        """Called when a non-annotated reference is updated."""

        for line in self.expand_lines(TAG_DELETED_TEMPLATE):
            yield line

        for line in ReferenceChange.generate_delete_summary(self, push):
            yield line


class OtherReferenceChange(ReferenceChange):
    refname_type = 'reference'

    def __init__(self, environment, refname, short_refname, old, new, rev):
        # We use the full refname as short_refname, because otherwise
        # the full name of the reference would not be obvious from the
        # text of the email.
        ReferenceChange.__init__(
            self, environment,
            refname=refname, short_refname=refname,
            old=old, new=new, rev=rev,
            )
        self.recipients = environment.get_refchange_recipients(self)


class Mailer(object):
    """An object that can send emails."""

    def send(self, lines, to_addrs):
        """Send an email consisting of lines.

        lines must be an iterable over the lines constituting the
        header and body of the email.  to_addrs is a list of recipient
        addresses (can be needed even if lines already contains a
        "To:" field).  It can be either a string (comma-separated list
        of email addresses) or a Python list of individual email
        addresses.

        """

        raise NotImplementedError()


class SendMailer(Mailer):
    """Send emails using 'sendmail -oi -t'."""

    SENDMAIL_CANDIDATES = [
        '/usr/sbin/sendmail',
        '/usr/lib/sendmail',
        ]

    @staticmethod
    def find_sendmail():
        for path in SendMailer.SENDMAIL_CANDIDATES:
            if os.access(path, os.X_OK):
                return path
        else:
            raise ConfigurationException(
                'No sendmail executable found.  '
                'Try setting multimailhook.sendmailCommand.'
                )

    def __init__(self, command=None, envelopesender=None):
        """Construct a SendMailer instance.

        command should be the command and arguments used to invoke
        sendmail, as a list of strings.  If an envelopesender is
        provided, it will also be passed to the command, via '-f
        envelopesender'."""

        if command:
            self.command = command[:]
        else:
            self.command = [self.find_sendmail(), '-oi', '-t']

        if envelopesender:
            self.command.extend(['-f', envelopesender])

    def send(self, lines, to_addrs):
        try:
            p = subprocess.Popen(self.command, stdin=subprocess.PIPE)
        except OSError:
            sys.stderr.write(
                '*** Cannot execute command: %s\n' % ' '.join(self.command) +
                '*** %s\n' % sys.exc_info()[1] +
                '*** Try setting multimailhook.mailer to "smtp"\n' +
                '*** to send emails without using the sendmail command.\n'
                )
            sys.exit(1)
        try:
            lines = (str_to_bytes(line) for line in lines)
            p.stdin.writelines(lines)
        except Exception:
            sys.stderr.write(
                '*** Error while generating commit email\n'
                '***  - mail sending aborted.\n'
                )
            try:
                # subprocess.terminate() is not available in Python 2.4
                p.terminate()
            except AttributeError:
                pass
            raise
        else:
            p.stdin.close()
            retcode = p.wait()
            if retcode:
                raise CommandError(self.command, retcode)


class SMTPMailer(Mailer):
    """Send emails using Python's smtplib."""

    def __init__(self, envelopesender, smtpserver,
                 smtpservertimeout=10.0, smtpserverdebuglevel=0,
                 smtpencryption='none',
                 smtpuser='', smtppass='',
                 smtpcacerts=''
                 ):
        if not envelopesender:
            sys.stderr.write(
                'fatal: git_multimail: cannot use SMTPMailer without a sender address.\n'
                'please set either multimailhook.envelopeSender or user.email\n'
                )
            sys.exit(1)
        if smtpencryption == 'ssl' and not (smtpuser and smtppass):
            raise ConfigurationException(
                'Cannot use SMTPMailer with security option ssl '
                'without options username and password.'
                )
        self.envelopesender = envelopesender
        self.smtpserver = smtpserver
        self.smtpservertimeout = smtpservertimeout
        self.smtpserverdebuglevel = smtpserverdebuglevel
        self.security = smtpencryption
        self.username = smtpuser
        self.password = smtppass
        self.smtpcacerts = smtpcacerts
        try:
            def call(klass, server, timeout):
                try:
                    return klass(server, timeout=timeout)
                except TypeError:
                    # Old Python versions do not have timeout= argument.
                    return klass(server)
            if self.security == 'none':
                self.smtp = call(smtplib.SMTP, self.smtpserver, timeout=self.smtpservertimeout)
            elif self.security == 'ssl':
                if self.smtpcacerts:
                    raise smtplib.SMTPException(
                        "Checking certificate is not supported for ssl, prefer starttls"
                        )
                self.smtp = call(smtplib.SMTP_SSL, self.smtpserver, timeout=self.smtpservertimeout)
            elif self.security == 'tls':
                if 'ssl' not in sys.modules:
                    sys.stderr.write(
                        '*** Your Python version does not have the ssl library installed\n'
                        '*** smtpEncryption=tls is not available.\n'
                        '*** Either upgrade Python to 2.6 or later\n'
                        '    or use git_multimail.py version 1.2.\n')
                if ':' not in self.smtpserver:
                    self.smtpserver += ':587'  # default port for TLS
                self.smtp = call(smtplib.SMTP, self.smtpserver, timeout=self.smtpservertimeout)
                # start: ehlo + starttls
                # equivalent to
                #     self.smtp.ehlo()
                #     self.smtp.starttls()
                # with acces to the ssl layer
                self.smtp.ehlo()
                if not self.smtp.has_extn("starttls"):
                    raise smtplib.SMTPException("STARTTLS extension not supported by server")
                resp, reply = self.smtp.docmd("STARTTLS")
                if resp != 220:
                    raise smtplib.SMTPException("Wrong answer to the STARTTLS command")
                if self.smtpcacerts:
                    self.smtp.sock = ssl.wrap_socket(
                        self.smtp.sock,
                        ca_certs=self.smtpcacerts,
                        cert_reqs=ssl.CERT_REQUIRED
                        )
                else:
                    self.smtp.sock = ssl.wrap_socket(
                        self.smtp.sock,
                        cert_reqs=ssl.CERT_NONE
                        )
                    sys.stderr.write(
                        '*** Warning, the server certificat is not verified (smtp) ***\n'
                        '***          set the option smtpCACerts                   ***\n'
                        )
                if not hasattr(self.smtp.sock, "read"):
                    # using httplib.FakeSocket with Python 2.5.x or earlier
                    self.smtp.sock.read = self.smtp.sock.recv
                self.smtp.file = smtplib.SSLFakeFile(self.smtp.sock)
                self.smtp.helo_resp = None
                self.smtp.ehlo_resp = None
                self.smtp.esmtp_features = {}
                self.smtp.does_esmtp = 0
                # end:   ehlo + starttls
                self.smtp.ehlo()
            else:
                sys.stdout.write('*** Error: Control reached an invalid option. ***')
                sys.exit(1)
            if self.smtpserverdebuglevel > 0:
                sys.stdout.write(
                    "*** Setting debug on for SMTP server connection (%s) ***\n"
                    % self.smtpserverdebuglevel)
                self.smtp.set_debuglevel(self.smtpserverdebuglevel)
        except Exception:
            sys.stderr.write(
                '*** Error establishing SMTP connection to %s ***\n'
                % self.smtpserver)
            sys.stderr.write('*** %s\n' % sys.exc_info()[1])
            sys.exit(1)

    def __del__(self):
        if hasattr(self, 'smtp'):
            self.smtp.quit()
            del self.smtp

    def send(self, lines, to_addrs):
        try:
            if self.username or self.password:
                self.smtp.login(self.username, self.password)
            msg = ''.join(lines)
            # turn comma-separated list into Python list if needed.
            if is_string(to_addrs):
                to_addrs = [email for (name, email) in getaddresses([to_addrs])]
            self.smtp.sendmail(self.envelopesender, to_addrs, msg)
        except smtplib.SMTPResponseException:
            sys.stderr.write('*** Error sending email ***\n')
            err = sys.exc_info()[1]
            sys.stderr.write('*** Error %d: %s\n' % (err.smtp_code,
                                                     bytes_to_str(err.smtp_error)))
            try:
                smtp = self.smtp
                # delete the field before quit() so that in case of
                # error, self.smtp is deleted anyway.
                del self.smtp
                smtp.quit()
            except:
                sys.stderr.write('*** Error closing the SMTP connection ***\n')
                sys.stderr.write('*** Exiting anyway ... ***\n')
                sys.stderr.write('*** %s\n' % sys.exc_info()[1])
            sys.exit(1)


class OutputMailer(Mailer):
    """Write emails to an output stream, bracketed by lines of '=' characters.

    This is intended for debugging purposes."""

    SEPARATOR = '=' * 75 + '\n'

    def __init__(self, f):
        self.f = f

    def send(self, lines, to_addrs):
        write_str(self.f, self.SEPARATOR)
        for line in lines:
            write_str(self.f, line)
        write_str(self.f, self.SEPARATOR)


def get_git_dir():
    """Determine GIT_DIR.

    Determine GIT_DIR either from the GIT_DIR environment variable or
    from the working directory, using Git's usual rules."""

    try:
        return read_git_output(['rev-parse', '--git-dir'])
    except CommandError:
        sys.stderr.write('fatal: git_multimail: not in a git directory\n')
        sys.exit(1)


class Environment(object):
    """Describes the environment in which the push is occurring.

    An Environment object encapsulates information about the local
    environment.  For example, it knows how to determine:

    * the name of the repository to which the push occurred

    * what user did the push

    * what users want to be informed about various types of changes.

    An Environment object is expected to have the following methods:

        get_repo_shortname()

            Return a short name for the repository, for display
            purposes.

        get_repo_path()

            Return the absolute path to the Git repository.

        get_emailprefix()

            Return a string that will be prefixed to every email's
            subject.

        get_pusher()

            Return the username of the person who pushed the changes.
            This value is used in the email body to indicate who
            pushed the change.

        get_pusher_email() (may return None)

            Return the email address of the person who pushed the
            changes.  The value should be a single RFC 2822 email
            address as a string; e.g., "Joe User <user@example.com>"
            if available, otherwise "user@example.com".  If set, the
            value is used as the Reply-To address for refchange
            emails.  If it is impossible to determine the pusher's
            email, this attribute should be set to None (in which case
            no Reply-To header will be output).

        get_sender()

            Return the address to be used as the 'From' email address
            in the email envelope.

        get_fromaddr(change=None)

            Return the 'From' email address used in the email 'From:'
            headers.  If the change is known when this function is
            called, it is passed in as the 'change' parameter.  (May
            be a full RFC 2822 email address like 'Joe User
            <user@example.com>'.)

        get_administrator()

            Return the name and/or email of the repository
            administrator.  This value is used in the footer as the
            person to whom requests to be removed from the
            notification list should be sent.  Ideally, it should
            include a valid email address.

        get_reply_to_refchange()
        get_reply_to_commit()

            Return the address to use in the email "Reply-To" header,
            as a string.  These can be an RFC 2822 email address, or
            None to omit the "Reply-To" header.
            get_reply_to_refchange() is used for refchange emails;
            get_reply_to_commit() is used for individual commit
            emails.

        get_ref_filter_regex()

            Return a tuple -- a compiled regex, and a boolean indicating
            whether the regex picks refs to include (if False, the regex
            matches on refs to exclude).

        get_default_ref_ignore_regex()

            Return a regex that should be ignored for both what emails
            to send and when computing what commits are considered new
            to the repository.  Default is "^refs/notes/".

    They should also define the following attributes:

        announce_show_shortlog (bool)

            True iff announce emails should include a shortlog.

        commit_email_format (string)

            If "html", generate commit emails in HTML instead of plain text
            used by default.

        html_in_intro (bool)
        html_in_footer (bool)

            When generating HTML emails, the introduction (respectively,
            the footer) will be HTML-escaped iff html_in_intro (respectively,
            the footer) is true. When false, only the values used to expand
            the template are escaped.

        refchange_showgraph (bool)

            True iff refchanges emails should include a detailed graph.

        refchange_showlog (bool)

            True iff refchanges emails should include a detailed log.

        diffopts (list of strings)

            The options that should be passed to 'git diff' for the
            summary email.  The value should be a list of strings
            representing words to be passed to the command.

        graphopts (list of strings)

            Analogous to diffopts, but contains options passed to
            'git log --graph' when generating the detailed graph for
            a set of commits (see refchange_showgraph)

        logopts (list of strings)

            Analogous to diffopts, but contains options passed to
            'git log' when generating the detailed log for a set of
            commits (see refchange_showlog)

        commitlogopts (list of strings)

            The options that should be passed to 'git log' for each
            commit mail.  The value should be a list of strings
            representing words to be passed to the command.

        date_substitute (string)

            String to be used in substitution for 'Date:' at start of
            line in the output of 'git log'.

        quiet (bool)
            On success do not write to stderr

        stdout (bool)
            Write email to stdout rather than emailing. Useful for debugging

        combine_when_single_commit (bool)

            True if a combined email should be produced when a single
            new commit is pushed to a branch, False otherwise.

        from_refchange, from_commit (strings)

            Addresses to use for the From: field for refchange emails
            and commit emails respectively.  Set from
            multimailhook.fromRefchange and multimailhook.fromCommit
            by ConfigEnvironmentMixin.

    """

    REPO_NAME_RE = re.compile(r'^(?P<name>.+?)(?:\.git)$')

    def __init__(self, osenv=None):
        self.osenv = osenv or os.environ
        self.announce_show_shortlog = False
        self.commit_email_format = "text"
        self.html_in_intro = False
        self.html_in_footer = False
        self.commitBrowseURL = None
        self.maxcommitemails = 500
        self.diffopts = ['--stat', '--summary', '--find-copies-harder']
        self.graphopts = ['--oneline', '--decorate']
        self.logopts = []
        self.refchange_showgraph = False
        self.refchange_showlog = False
        self.commitlogopts = ['-C', '--stat', '-p', '--cc']
        self.date_substitute = 'AuthorDate: '
        self.quiet = False
        self.stdout = False
        self.combine_when_single_commit = True

        self.COMPUTED_KEYS = [
            'administrator',
            'charset',
            'emailprefix',
            'pusher',
            'pusher_email',
            'repo_path',
            'repo_shortname',
            'sender',
            ]

        self._values = None

    def get_repo_shortname(self):
        """Use the last part of the repo path, with ".git" stripped off if present."""

        basename = os.path.basename(os.path.abspath(self.get_repo_path()))
        m = self.REPO_NAME_RE.match(basename)
        if m:
            return m.group('name')
        else:
            return basename

    def get_pusher(self):
        raise NotImplementedError()

    def get_pusher_email(self):
        return None

    def get_fromaddr(self, change=None):
        config = Config('user')
        fromname = config.get('name', default='')
        fromemail = config.get('email', default='')
        if fromemail:
            return formataddr([fromname, fromemail])
        return self.get_sender()

    def get_administrator(self):
        return 'the administrator of this repository'

    def get_emailprefix(self):
        return ''

    def get_repo_path(self):
        if read_git_output(['rev-parse', '--is-bare-repository']) == 'true':
            path = get_git_dir()
        else:
            path = read_git_output(['rev-parse', '--show-toplevel'])
        return os.path.abspath(path)

    def get_charset(self):
        return CHARSET

    def get_values(self):
        """Return a dictionary {keyword: expansion} for this Environment.

        This method is called by Change._compute_values().  The keys
        in the returned dictionary are available to be used in any of
        the templates.  The dictionary is created by calling
        self.get_NAME() for each of the attributes named in
        COMPUTED_KEYS and recording those that do not return None.
        The return value is always a new dictionary."""

        if self._values is None:
            values = {'': ''}  # %()s expands to the empty string.

            for key in self.COMPUTED_KEYS:
                value = getattr(self, 'get_%s' % (key,))()
                if value is not None:
                    values[key] = value

            self._values = values

        return self._values.copy()

    def get_refchange_recipients(self, refchange):
        """Return the recipients for notifications about refchange.

        Return the list of email addresses to which notifications
        about the specified ReferenceChange should be sent."""

        raise NotImplementedError()

    def get_announce_recipients(self, annotated_tag_change):
        """Return the recipients for notifications about annotated_tag_change.

        Return the list of email addresses to which notifications
        about the specified AnnotatedTagChange should be sent."""

        raise NotImplementedError()

    def get_reply_to_refchange(self, refchange):
        return self.get_pusher_email()

    def get_revision_recipients(self, revision):
        """Return the recipients for messages about revision.

        Return the list of email addresses to which notifications
        about the specified Revision should be sent.  This method
        could be overridden, for example, to take into account the
        contents of the revision when deciding whom to notify about
        it.  For example, there could be a scheme for users to express
        interest in particular files or subdirectories, and only
        receive notification emails for revisions that affecting those
        files."""

        raise NotImplementedError()

    def get_reply_to_commit(self, revision):
        return revision.author

    def get_default_ref_ignore_regex(self):
        # The commit messages of git notes are essentially meaningless
        # and "filenames" in git notes commits are an implementational
        # detail that might surprise users at first.  As such, we
        # would need a completely different method for handling emails
        # of git notes in order for them to be of benefit for users,
        # which we simply do not have right now.
        return "^refs/notes/"

    def filter_body(self, lines):
        """Filter the lines intended for an email body.

        lines is an iterable over the lines that would go into the
        email body.  Filter it (e.g., limit the number of lines, the
        line length, character set, etc.), returning another iterable.
        See FilterLinesEnvironmentMixin and MaxlinesEnvironmentMixin
        for classes implementing this functionality."""

        return lines

    def log_msg(self, msg):
        """Write the string msg on a log file or on stderr.

        Sends the text to stderr by default, override to change the behavior."""
        write_str(sys.stderr, msg)

    def log_warning(self, msg):
        """Write the string msg on a log file or on stderr.

        Sends the text to stderr by default, override to change the behavior."""
        write_str(sys.stderr, msg)

    def log_error(self, msg):
        """Write the string msg on a log file or on stderr.

        Sends the text to stderr by default, override to change the behavior."""
        write_str(sys.stderr, msg)


class ConfigEnvironmentMixin(Environment):
    """A mixin that sets self.config to its constructor's config argument.

    This class's constructor consumes the "config" argument.

    Mixins that need to inspect the config should inherit from this
    class (1) to make sure that "config" is still in the constructor
    arguments with its own constructor runs and/or (2) to be sure that
    self.config is set after construction."""

    def __init__(self, config, **kw):
        super(ConfigEnvironmentMixin, self).__init__(**kw)
        self.config = config


class ConfigOptionsEnvironmentMixin(ConfigEnvironmentMixin):
    """An Environment that reads most of its information from "git config"."""

    @staticmethod
    def forbid_field_values(name, value, forbidden):
        for forbidden_val in forbidden:
            if value is not None and value.lower() == forbidden:
                raise ConfigurationException(
                    '"%s" is not an allowed setting for %s' % (value, name)
                    )

    def __init__(self, config, **kw):
        super(ConfigOptionsEnvironmentMixin, self).__init__(
            config=config, **kw
            )

        for var, cfg in (
                ('announce_show_shortlog', 'announceshortlog'),
                ('refchange_showgraph', 'refchangeShowGraph'),
                ('refchange_showlog', 'refchangeshowlog'),
                ('quiet', 'quiet'),
                ('stdout', 'stdout'),
                ):
            val = config.get_bool(cfg)
            if val is not None:
                setattr(self, var, val)

        commit_email_format = config.get('commitEmailFormat')
        if commit_email_format is not None:
            if commit_email_format != "html" and commit_email_format != "text":
                self.log_warning(
                    '*** Unknown value for multimailhook.commitEmailFormat: %s\n' %
                    commit_email_format +
                    '*** Expected either "text" or "html".  Ignoring.\n'
                    )
            else:
                self.commit_email_format = commit_email_format

        html_in_intro = config.get_bool('htmlInIntro')
        if html_in_intro is not None:
            self.html_in_intro = html_in_intro

        html_in_footer = config.get_bool('htmlInFooter')
        if html_in_footer is not None:
            self.html_in_footer = html_in_footer

        self.commitBrowseURL = config.get('commitBrowseURL')

        maxcommitemails = config.get('maxcommitemails')
        if maxcommitemails is not None:
            try:
                self.maxcommitemails = int(maxcommitemails)
            except ValueError:
                self.log_warning(
                    '*** Malformed value for multimailhook.maxCommitEmails: %s\n'
                    % maxcommitemails +
                    '*** Expected a number.  Ignoring.\n'
                    )

        diffopts = config.get('diffopts')
        if diffopts is not None:
            self.diffopts = shlex.split(diffopts)

        graphopts = config.get('graphOpts')
        if graphopts is not None:
            self.graphopts = shlex.split(graphopts)

        logopts = config.get('logopts')
        if logopts is not None:
            self.logopts = shlex.split(logopts)

        commitlogopts = config.get('commitlogopts')
        if commitlogopts is not None:
            self.commitlogopts = shlex.split(commitlogopts)

        date_substitute = config.get('dateSubstitute')
        if date_substitute == 'none':
            self.date_substitute = None
        elif date_substitute is not None:
            self.date_substitute = date_substitute

        reply_to = config.get('replyTo')
        self.__reply_to_refchange = config.get('replyToRefchange', default=reply_to)
        self.forbid_field_values('replyToRefchange',
                                 self.__reply_to_refchange,
                                 ['author'])
        self.__reply_to_commit = config.get('replyToCommit', default=reply_to)

        self.from_refchange = config.get('fromRefchange')
        self.forbid_field_values('fromRefchange',
                                 self.from_refchange,
                                 ['author', 'none'])
        self.from_commit = config.get('fromCommit')
        self.forbid_field_values('fromCommit',
                                 self.from_commit,
                                 ['none'])

        combine = config.get_bool('combineWhenSingleCommit')
        if combine is not None:
            self.combine_when_single_commit = combine

    def get_administrator(self):
        return (
            self.config.get('administrator') or
            self.get_sender() or
            super(ConfigOptionsEnvironmentMixin, self).get_administrator()
            )

    def get_repo_shortname(self):
        return (
            self.config.get('reponame') or
            super(ConfigOptionsEnvironmentMixin, self).get_repo_shortname()
            )

    def get_emailprefix(self):
        emailprefix = self.config.get('emailprefix')
        if emailprefix is not None:
            emailprefix = emailprefix.strip()
            if emailprefix:
                return emailprefix + ' '
            else:
                return ''
        else:
            return '[%s] ' % (self.get_repo_shortname(),)

    def get_sender(self):
        return self.config.get('envelopesender')

    def process_addr(self, addr, change):
        if addr.lower() == 'author':
            if hasattr(change, 'author'):
                return change.author
            else:
                return None
        elif addr.lower() == 'pusher':
            return self.get_pusher_email()
        elif addr.lower() == 'none':
            return None
        else:
            return addr

    def get_fromaddr(self, change=None):
        fromaddr = self.config.get('from')
        if change:
            alt_fromaddr = change.get_alt_fromaddr()
            if alt_fromaddr:
                fromaddr = alt_fromaddr
        if fromaddr:
            fromaddr = self.process_addr(fromaddr, change)
        if fromaddr:
            return fromaddr
        return super(ConfigOptionsEnvironmentMixin, self).get_fromaddr(change)

    def get_reply_to_refchange(self, refchange):
        if self.__reply_to_refchange is None:
            return super(ConfigOptionsEnvironmentMixin, self).get_reply_to_refchange(refchange)
        else:
            return self.process_addr(self.__reply_to_refchange, refchange)

    def get_reply_to_commit(self, revision):
        if self.__reply_to_commit is None:
            return super(ConfigOptionsEnvironmentMixin, self).get_reply_to_commit(revision)
        else:
            return self.process_addr(self.__reply_to_commit, revision)

    def get_scancommitforcc(self):
        return self.config.get('scancommitforcc')


class FilterLinesEnvironmentMixin(Environment):
    """Handle encoding and maximum line length of body lines.

        emailmaxlinelength (int or None)

            The maximum length of any single line in the email body.
            Longer lines are truncated at that length with ' [...]'
            appended.

        strict_utf8 (bool)

            If this field is set to True, then the email body text is
            expected to be UTF-8.  Any invalid characters are
            converted to U+FFFD, the Unicode replacement character
            (encoded as UTF-8, of course).

    """

    def __init__(self, strict_utf8=True, emailmaxlinelength=500, **kw):
        super(FilterLinesEnvironmentMixin, self).__init__(**kw)
        self.__strict_utf8 = strict_utf8
        self.__emailmaxlinelength = emailmaxlinelength

    def filter_body(self, lines):
        lines = super(FilterLinesEnvironmentMixin, self).filter_body(lines)
        if self.__strict_utf8:
            if not PYTHON3:
                lines = (line.decode(ENCODING, 'replace') for line in lines)
            # Limit the line length in Unicode-space to avoid
            # splitting characters:
            if self.__emailmaxlinelength:
                lines = limit_linelength(lines, self.__emailmaxlinelength)
            if not PYTHON3:
                lines = (line.encode(ENCODING, 'replace') for line in lines)
        elif self.__emailmaxlinelength:
            lines = limit_linelength(lines, self.__emailmaxlinelength)

        return lines


class ConfigFilterLinesEnvironmentMixin(
        ConfigEnvironmentMixin,
        FilterLinesEnvironmentMixin,
        ):
    """Handle encoding and maximum line length based on config."""

    def __init__(self, config, **kw):
        strict_utf8 = config.get_bool('emailstrictutf8', default=None)
        if strict_utf8 is not None:
            kw['strict_utf8'] = strict_utf8

        emailmaxlinelength = config.get('emailmaxlinelength')
        if emailmaxlinelength is not None:
            kw['emailmaxlinelength'] = int(emailmaxlinelength)

        super(ConfigFilterLinesEnvironmentMixin, self).__init__(
            config=config, **kw
            )


class MaxlinesEnvironmentMixin(Environment):
    """Limit the email body to a specified number of lines."""

    def __init__(self, emailmaxlines, **kw):
        super(MaxlinesEnvironmentMixin, self).__init__(**kw)
        self.__emailmaxlines = emailmaxlines

    def filter_body(self, lines):
        lines = super(MaxlinesEnvironmentMixin, self).filter_body(lines)
        if self.__emailmaxlines:
            lines = limit_lines(lines, self.__emailmaxlines)
        return lines


class ConfigMaxlinesEnvironmentMixin(
        ConfigEnvironmentMixin,
        MaxlinesEnvironmentMixin,
        ):
    """Limit the email body to the number of lines specified in config."""

    def __init__(self, config, **kw):
        emailmaxlines = int(config.get('emailmaxlines', default='0'))
        super(ConfigMaxlinesEnvironmentMixin, self).__init__(
            config=config,
            emailmaxlines=emailmaxlines,
            **kw
            )


class FQDNEnvironmentMixin(Environment):
    """A mixin that sets the host's FQDN to its constructor argument."""

    def __init__(self, fqdn, **kw):
        super(FQDNEnvironmentMixin, self).__init__(**kw)
        self.COMPUTED_KEYS += ['fqdn']
        self.__fqdn = fqdn

    def get_fqdn(self):
        """Return the fully-qualified domain name for this host.

        Return None if it is unavailable or unwanted."""

        return self.__fqdn


class ConfigFQDNEnvironmentMixin(
        ConfigEnvironmentMixin,
        FQDNEnvironmentMixin,
        ):
    """Read the FQDN from the config."""

    def __init__(self, config, **kw):
        fqdn = config.get('fqdn')
        super(ConfigFQDNEnvironmentMixin, self).__init__(
            config=config,
            fqdn=fqdn,
            **kw
            )


class ComputeFQDNEnvironmentMixin(FQDNEnvironmentMixin):
    """Get the FQDN by calling socket.getfqdn()."""

    def __init__(self, **kw):
        super(ComputeFQDNEnvironmentMixin, self).__init__(
            fqdn=socket.getfqdn(),
            **kw
            )


class PusherDomainEnvironmentMixin(ConfigEnvironmentMixin):
    """Deduce pusher_email from pusher by appending an emaildomain."""

    def __init__(self, **kw):
        super(PusherDomainEnvironmentMixin, self).__init__(**kw)
        self.__emaildomain = self.config.get('emaildomain')

    def get_pusher_email(self):
        if self.__emaildomain:
            # Derive the pusher's full email address in the default way:
            return '%s@%s' % (self.get_pusher(), self.__emaildomain)
        else:
            return super(PusherDomainEnvironmentMixin, self).get_pusher_email()


class StaticRecipientsEnvironmentMixin(Environment):
    """Set recipients statically based on constructor parameters."""

    def __init__(
            self,
            refchange_recipients, announce_recipients, revision_recipients, scancommitforcc,
            **kw
            ):
        super(StaticRecipientsEnvironmentMixin, self).__init__(**kw)

        # The recipients for various types of notification emails, as
        # RFC 2822 email addresses separated by commas (or the empty
        # string if no recipients are configured).  Although there is
        # a mechanism to choose the recipient lists based on on the
        # actual *contents* of the change being reported, we only
        # choose based on the *type* of the change.  Therefore we can
        # compute them once and for all:
        if not (refchange_recipients or
                announce_recipients or
                revision_recipients or
                scancommitforcc):
            raise ConfigurationException('No email recipients configured!')
        self.__refchange_recipients = refchange_recipients
        self.__announce_recipients = announce_recipients
        self.__revision_recipients = revision_recipients

    def get_refchange_recipients(self, refchange):
        return self.__refchange_recipients

    def get_announce_recipients(self, annotated_tag_change):
        return self.__announce_recipients

    def get_revision_recipients(self, revision):
        return self.__revision_recipients


class ConfigRecipientsEnvironmentMixin(
        ConfigEnvironmentMixin,
        StaticRecipientsEnvironmentMixin
        ):
    """Determine recipients statically based on config."""

    def __init__(self, config, **kw):
        super(ConfigRecipientsEnvironmentMixin, self).__init__(
            config=config,
            refchange_recipients=self._get_recipients(
                config, 'refchangelist', 'mailinglist',
                ),
            announce_recipients=self._get_recipients(
                config, 'announcelist', 'refchangelist', 'mailinglist',
                ),
            revision_recipients=self._get_recipients(
                config, 'commitlist', 'mailinglist',
                ),
            scancommitforcc=config.get('scancommitforcc'),
            **kw
            )

    def _get_recipients(self, config, *names):
        """Return the recipients for a particular type of message.

        Return the list of email addresses to which a particular type
        of notification email should be sent, by looking at the config
        value for "multimailhook.$name" for each of names.  Use the
        value from the first name that is configured.  The return
        value is a (possibly empty) string containing RFC 2822 email
        addresses separated by commas.  If no configuration could be
        found, raise a ConfigurationException."""

        for name in names:
            lines = config.get_all(name)
            if lines is not None:
                lines = [line.strip() for line in lines]
                # Single "none" is a special value equivalen to empty string.
                if lines == ['none']:
                    lines = ['']
                return ', '.join(lines)
        else:
            return ''


class StaticRefFilterEnvironmentMixin(Environment):
    """Set branch filter statically based on constructor parameters."""

    def __init__(self, ref_filter_incl_regex, ref_filter_excl_regex,
                 ref_filter_do_send_regex, ref_filter_dont_send_regex,
                 **kw):
        super(StaticRefFilterEnvironmentMixin, self).__init__(**kw)

        if ref_filter_incl_regex and ref_filter_excl_regex:
            raise ConfigurationException(
                "Cannot specify both a ref inclusion and exclusion regex.")
        self.__is_inclusion_filter = bool(ref_filter_incl_regex)
        default_exclude = self.get_default_ref_ignore_regex()
        if ref_filter_incl_regex:
            ref_filter_regex = ref_filter_incl_regex
        elif ref_filter_excl_regex:
            ref_filter_regex = ref_filter_excl_regex + '|' + default_exclude
        else:
            ref_filter_regex = default_exclude
        try:
            self.__compiled_regex = re.compile(ref_filter_regex)
        except Exception:
            raise ConfigurationException(
                'Invalid Ref Filter Regex "%s": %s' % (ref_filter_regex, sys.exc_info()[1]))

        if ref_filter_do_send_regex and ref_filter_dont_send_regex:
            raise ConfigurationException(
                "Cannot specify both a ref doSend and dontSend regex.")
        if ref_filter_do_send_regex or ref_filter_dont_send_regex:
            self.__is_do_send_filter = bool(ref_filter_do_send_regex)
            if ref_filter_incl_regex:
                ref_filter_send_regex = ref_filter_incl_regex
            elif ref_filter_excl_regex:
                ref_filter_send_regex = ref_filter_excl_regex
            else:
                ref_filter_send_regex = '.*'
                self.__is_do_send_filter = True
            try:
                self.__send_compiled_regex = re.compile(ref_filter_send_regex)
            except Exception:
                raise ConfigurationException(
                    'Invalid Ref Filter Regex "%s": %s' %
                    (ref_filter_send_regex, sys.exc_info()[1]))
        else:
            self.__send_compiled_regex = self.__compiled_regex
            self.__is_do_send_filter = self.__is_inclusion_filter

    def get_ref_filter_regex(self, send_filter=False):
        if send_filter:
            return self.__send_compiled_regex, self.__is_do_send_filter
        else:
            return self.__compiled_regex, self.__is_inclusion_filter


class ConfigRefFilterEnvironmentMixin(
        ConfigEnvironmentMixin,
        StaticRefFilterEnvironmentMixin
        ):
    """Determine branch filtering statically based on config."""

    def _get_regex(self, config, key):
        """Get a list of whitespace-separated regex. The refFilter* config
        variables are multivalued (hence the use of get_all), and we
        allow each entry to be a whitespace-separated list (hence the
        split on each line). The whole thing is glued into a single regex."""
        values = config.get_all(key)
        if values is None:
            return values
        items = []
        for line in values:
            for i in line.split():
                items.append(i)
        if items == []:
            return None
        return '|'.join(items)

    def __init__(self, config, **kw):
        super(ConfigRefFilterEnvironmentMixin, self).__init__(
            config=config,
            ref_filter_incl_regex=self._get_regex(config, 'refFilterInclusionRegex'),
            ref_filter_excl_regex=self._get_regex(config, 'refFilterExclusionRegex'),
            ref_filter_do_send_regex=self._get_regex(config, 'refFilterDoSendRegex'),
            ref_filter_dont_send_regex=self._get_regex(config, 'refFilterDontSendRegex'),
            **kw
            )


class ProjectdescEnvironmentMixin(Environment):
    """Make a "projectdesc" value available for templates.

    By default, it is set to the first line of $GIT_DIR/description
    (if that file is present and appears to be set meaningfully)."""

    def __init__(self, **kw):
        super(ProjectdescEnvironmentMixin, self).__init__(**kw)
        self.COMPUTED_KEYS += ['projectdesc']

    def get_projectdesc(self):
        """Return a one-line descripition of the project."""

        git_dir = get_git_dir()
        try:
            projectdesc = open(os.path.join(git_dir, 'description')).readline().strip()
            if projectdesc and not projectdesc.startswith('Unnamed repository'):
                return projectdesc
        except IOError:
            pass

        return 'UNNAMED PROJECT'


class GenericEnvironmentMixin(Environment):
    def get_pusher(self):
        return self.osenv.get('USER', self.osenv.get('USERNAME', 'unknown user'))


class GenericEnvironment(
        ProjectdescEnvironmentMixin,
        ConfigMaxlinesEnvironmentMixin,
        ComputeFQDNEnvironmentMixin,
        ConfigFilterLinesEnvironmentMixin,
        ConfigRecipientsEnvironmentMixin,
        ConfigRefFilterEnvironmentMixin,
        PusherDomainEnvironmentMixin,
        ConfigOptionsEnvironmentMixin,
        GenericEnvironmentMixin,
        Environment,
        ):
    pass


class GitoliteEnvironmentMixin(Environment):
    def get_repo_shortname(self):
        # The gitolite environment variable $GL_REPO is a pretty good
        # repo_shortname (though it's probably not as good as a value
        # the user might have explicitly put in his config).
        return (
            self.osenv.get('GL_REPO', None) or
            super(GitoliteEnvironmentMixin, self).get_repo_shortname()
            )

    def get_pusher(self):
        return self.osenv.get('GL_USER', 'unknown user')

    def get_fromaddr(self, change=None):
        GL_USER = self.osenv.get('GL_USER')
        if GL_USER is not None:
            # Find the path to gitolite.conf.  Note that gitolite v3
            # did away with the GL_ADMINDIR and GL_CONF environment
            # variables (they are now hard-coded).
            GL_ADMINDIR = self.osenv.get(
                'GL_ADMINDIR',
                os.path.expanduser(os.path.join('~', '.gitolite')))
            GL_CONF = self.osenv.get(
                'GL_CONF',
                os.path.join(GL_ADMINDIR, 'conf', 'gitolite.conf'))
            if os.path.isfile(GL_CONF):
                f = open(GL_CONF, 'rU')
                try:
                    in_user_emails_section = False
                    re_template = r'^\s*#\s*%s\s*$'
                    re_begin, re_user, re_end = (
                        re.compile(re_template % x)
                        for x in (
                            r'BEGIN\s+USER\s+EMAILS',
                            re.escape(GL_USER) + r'\s+(.*)',
                            r'END\s+USER\s+EMAILS',
                            ))
                    for l in f:
                        l = l.rstrip('\n')
                        if not in_user_emails_section:
                            if re_begin.match(l):
                                in_user_emails_section = True
                            continue
                        if re_end.match(l):
                            break
                        m = re_user.match(l)
                        if m:
                            return m.group(1)
                finally:
                    f.close()
        return super(GitoliteEnvironmentMixin, self).get_fromaddr(change)


class IncrementalDateTime(object):
    """Simple wrapper to give incremental date/times.

    Each call will result in a date/time a second later than the
    previous call.  This can be used to falsify email headers, to
    increase the likelihood that email clients sort the emails
    correctly."""

    def __init__(self):
        self.time = time.time()
        self.next = self.__next__  # Python 2 backward compatibility

    def __next__(self):
        formatted = formatdate(self.time, True)
        self.time += 1
        return formatted


class GitoliteEnvironment(
        ProjectdescEnvironmentMixin,
        ConfigMaxlinesEnvironmentMixin,
        ComputeFQDNEnvironmentMixin,
        ConfigFilterLinesEnvironmentMixin,
        ConfigRecipientsEnvironmentMixin,
        ConfigRefFilterEnvironmentMixin,
        PusherDomainEnvironmentMixin,
        ConfigOptionsEnvironmentMixin,
        GitoliteEnvironmentMixin,
        Environment,
        ):
    pass


class StashEnvironmentMixin(Environment):
    def __init__(self, user=None, repo=None, **kw):
        super(StashEnvironmentMixin, self).__init__(**kw)
        self.__user = user
        self.__repo = repo

    def get_repo_shortname(self):
        return self.__repo

    def get_pusher(self):
        return re.match('(.*?)\s*<', self.__user).group(1)

    def get_pusher_email(self):
        return self.__user

    def get_fromaddr(self, change=None):
        return self.__user


class StashEnvironment(
        StashEnvironmentMixin,
        ProjectdescEnvironmentMixin,
        ConfigMaxlinesEnvironmentMixin,
        ComputeFQDNEnvironmentMixin,
        ConfigFilterLinesEnvironmentMixin,
        ConfigRecipientsEnvironmentMixin,
        ConfigRefFilterEnvironmentMixin,
        PusherDomainEnvironmentMixin,
        ConfigOptionsEnvironmentMixin,
        Environment,
        ):
    pass


class GerritEnvironmentMixin(Environment):
    def __init__(self, project=None, submitter=None, update_method=None, **kw):
        super(GerritEnvironmentMixin, self).__init__(**kw)
        self.__project = project
        self.__submitter = submitter
        self.__update_method = update_method
        "Make an 'update_method' value available for templates."
        self.COMPUTED_KEYS += ['update_method']

    def get_repo_shortname(self):
        return self.__project

    def get_pusher(self):
        if self.__submitter:
            if self.__submitter.find('<') != -1:
                # Submitter has a configured email, we transformed
                # __submitter into an RFC 2822 string already.
                return re.match('(.*?)\s*<', self.__submitter).group(1)
            else:
                # Submitter has no configured email, it's just his name.
                return self.__submitter
        else:
            # If we arrive here, this means someone pushed "Submit" from
            # the gerrit web UI for the CR (or used one of the programmatic
            # APIs to do the same, such as gerrit review) and the
            # merge/push was done by the Gerrit user.  It was technically
            # triggered by someone else, but sadly we have no way of
            # determining who that someone else is at this point.
            return 'Gerrit'  # 'unknown user'?

    def get_pusher_email(self):
        if self.__submitter:
            return self.__submitter
        else:
            return super(GerritEnvironmentMixin, self).get_pusher_email()

    def get_fromaddr(self, change=None):
        if self.__submitter and self.__submitter.find('<') != -1:
            return self.__submitter
        else:
            return super(GerritEnvironmentMixin, self).get_fromaddr(change)

    def get_default_ref_ignore_regex(self):
        default = super(GerritEnvironmentMixin, self).get_default_ref_ignore_regex()
        return default + '|^refs/changes/|^refs/cache-automerge/|^refs/meta/'

    def get_revision_recipients(self, revision):
        # Merge commits created by Gerrit when users hit "Submit this patchset"
        # in the Web UI (or do equivalently with REST APIs or the gerrit review
        # command) are not something users want to see an individual email for.
        # Filter them out.
        committer = read_git_output(['log', '--no-walk', '--format=%cN',
                                     revision.rev.sha1])
        if committer == 'Gerrit Code Review':
            return []
        else:
            return super(GerritEnvironmentMixin, self).get_revision_recipients(revision)

    def get_update_method(self):
        return self.__update_method


class GerritEnvironment(
        GerritEnvironmentMixin,
        ProjectdescEnvironmentMixin,
        ConfigMaxlinesEnvironmentMixin,
        ComputeFQDNEnvironmentMixin,
        ConfigFilterLinesEnvironmentMixin,
        ConfigRecipientsEnvironmentMixin,
        ConfigRefFilterEnvironmentMixin,
        PusherDomainEnvironmentMixin,
        ConfigOptionsEnvironmentMixin,
        Environment,
        ):
    pass


class Push(object):
    """Represent an entire push (i.e., a group of ReferenceChanges).

    It is easy to figure out what commits were added to a *branch* by
    a Reference change:

        git rev-list change.old..change.new

    or removed from a *branch*:

        git rev-list change.new..change.old

    But it is not quite so trivial to determine which entirely new
    commits were added to the *repository* by a push and which old
    commits were discarded by a push.  A big part of the job of this
    class is to figure out these things, and to make sure that new
    commits are only detailed once even if they were added to multiple
    references.

    The first step is to determine the "other" references--those
    unaffected by the current push.  They are computed by listing all
    references then removing any affected by this push.  The results
    are stored in Push._other_ref_sha1s.

    The commits contained in the repository before this push were

        git rev-list other1 other2 other3 ... change1.old change2.old ...

    Where "changeN.old" is the old value of one of the references
    affected by this push.

    The commits contained in the repository after this push are

        git rev-list other1 other2 other3 ... change1.new change2.new ...

    The commits added by this push are the difference between these
    two sets, which can be written

        git rev-list \
            ^other1 ^other2 ... \
            ^change1.old ^change2.old ... \
            change1.new change2.new ...

    The commits removed by this push can be computed by

        git rev-list \
            ^other1 ^other2 ... \
            ^change1.new ^change2.new ... \
            change1.old change2.old ...

    The last point is that it is possible that other pushes are
    occurring simultaneously to this one, so reference values can
    change at any time.  It is impossible to eliminate all race
    conditions, but we reduce the window of time during which problems
    can occur by translating reference names to SHA1s as soon as
    possible and working with SHA1s thereafter (because SHA1s are
    immutable)."""

    # A map {(changeclass, changetype): integer} specifying the order
    # that reference changes will be processed if multiple reference
    # changes are included in a single push.  The order is significant
    # mostly because new commit notifications are threaded together
    # with the first reference change that includes the commit.  The
    # following order thus causes commits to be grouped with branch
    # changes (as opposed to tag changes) if possible.
    SORT_ORDER = dict(
        (value, i) for (i, value) in enumerate([
            (BranchChange, 'update'),
            (BranchChange, 'create'),
            (AnnotatedTagChange, 'update'),
            (AnnotatedTagChange, 'create'),
            (NonAnnotatedTagChange, 'update'),
            (NonAnnotatedTagChange, 'create'),
            (BranchChange, 'delete'),
            (AnnotatedTagChange, 'delete'),
            (NonAnnotatedTagChange, 'delete'),
            (OtherReferenceChange, 'update'),
            (OtherReferenceChange, 'create'),
            (OtherReferenceChange, 'delete'),
            ])
        )

    def __init__(self, environment, changes, ignore_other_refs=False):
        self.changes = sorted(changes, key=self._sort_key)
        self.__other_ref_sha1s = None
        self.__cached_commits_spec = {}
        self.environment = environment

        if ignore_other_refs:
            self.__other_ref_sha1s = set()

    @classmethod
    def _sort_key(klass, change):
        return (klass.SORT_ORDER[change.__class__, change.change_type], change.refname,)

    @property
    def _other_ref_sha1s(self):
        """The GitObjects referred to by references unaffected by this push.
        """
        if self.__other_ref_sha1s is None:
            # The refnames being changed by this push:
            updated_refs = set(
                change.refname
                for change in self.changes
                )

            # The SHA-1s of commits referred to by all references in this
            # repository *except* updated_refs:
            sha1s = set()
            fmt = (
                '%(objectname) %(objecttype) %(refname)\n'
                '%(*objectname) %(*objecttype) %(refname)'
                )
            ref_filter_regex, is_inclusion_filter = \
                self.environment.get_ref_filter_regex()
            for line in read_git_lines(
                    ['for-each-ref', '--format=%s' % (fmt,)]):
                (sha1, type, name) = line.split(' ', 2)
                if (sha1 and type == 'commit' and
                        name not in updated_refs and
                        include_ref(name, ref_filter_regex, is_inclusion_filter)):
                    sha1s.add(sha1)

            self.__other_ref_sha1s = sha1s

        return self.__other_ref_sha1s

    def _get_commits_spec_incl(self, new_or_old, reference_change=None):
        """Get new or old SHA-1 from one or each of the changed refs.

        Return a list of SHA-1 commit identifier strings suitable as
        arguments to 'git rev-list' (or 'git log' or ...).  The
        returned identifiers are either the old or new values from one
        or all of the changed references, depending on the values of
        new_or_old and reference_change.

        new_or_old is either the string 'new' or the string 'old'.  If
        'new', the returned SHA-1 identifiers are the new values from
        each changed reference.  If 'old', the SHA-1 identifiers are
        the old values from each changed reference.

        If reference_change is specified and not None, only the new or
        old reference from the specified reference is included in the
        return value.

        This function returns None if there are no matching revisions
        (e.g., because a branch was deleted and new_or_old is 'new').
        """

        if not reference_change:
            incl_spec = sorted(
                getattr(change, new_or_old).sha1
                for change in self.changes
                if getattr(change, new_or_old)
                )
            if not incl_spec:
                incl_spec = None
        elif not getattr(reference_change, new_or_old).commit_sha1:
            incl_spec = None
        else:
            incl_spec = [getattr(reference_change, new_or_old).commit_sha1]
        return incl_spec

    def _get_commits_spec_excl(self, new_or_old):
        """Get exclusion revisions for determining new or discarded commits.

        Return a list of strings suitable as arguments to 'git
        rev-list' (or 'git log' or ...) that will exclude all
        commits that, depending on the value of new_or_old, were
        either previously in the repository (useful for determining
        which commits are new to the repository) or currently in the
        repository (useful for determining which commits were
        discarded from the repository).

        new_or_old is either the string 'new' or the string 'old'.  If
        'new', the commits to be excluded are those that were in the
        repository before the push.  If 'old', the commits to be
        excluded are those that are currently in the repository.  """

        old_or_new = {'old': 'new', 'new': 'old'}[new_or_old]
        excl_revs = self._other_ref_sha1s.union(
            getattr(change, old_or_new).sha1
            for change in self.changes
            if getattr(change, old_or_new).type in ['commit', 'tag']
            )
        return ['^' + sha1 for sha1 in sorted(excl_revs)]

    def get_commits_spec(self, new_or_old, reference_change=None):
        """Get rev-list arguments for added or discarded commits.

        Return a list of strings suitable as arguments to 'git
        rev-list' (or 'git log' or ...) that select those commits
        that, depending on the value of new_or_old, are either new to
        the repository or were discarded from the repository.

        new_or_old is either the string 'new' or the string 'old'.  If
        'new', the returned list is used to select commits that are
        new to the repository.  If 'old', the returned value is used
        to select the commits that have been discarded from the
        repository.

        If reference_change is specified and not None, the new or
        discarded commits are limited to those that are reachable from
        the new or old value of the specified reference.

        This function returns None if there are no added (or discarded)
        revisions.
        """
        key = (new_or_old, reference_change)
        if key not in self.__cached_commits_spec:
            ret = self._get_commits_spec_incl(new_or_old, reference_change)
            if ret is not None:
                ret.extend(self._get_commits_spec_excl(new_or_old))
            self.__cached_commits_spec[key] = ret
        return self.__cached_commits_spec[key]

    def get_new_commits(self, reference_change=None):
        """Return a list of commits added by this push.

        Return a list of the object names of commits that were added
        by the part of this push represented by reference_change.  If
        reference_change is None, then return a list of *all* commits
        added by this push."""

        spec = self.get_commits_spec('new', reference_change)
        return git_rev_list(spec)

    def get_discarded_commits(self, reference_change):
        """Return a list of commits discarded by this push.

        Return a list of the object names of commits that were
        entirely discarded from the repository by the part of this
        push represented by reference_change."""

        spec = self.get_commits_spec('old', reference_change)
        return git_rev_list(spec)

    def send_emails(self, mailer, body_filter=None):
        """Use send all of the notification emails needed for this push.

        Use send all of the notification emails (including reference
        change emails and commit emails) needed for this push.  Send
        the emails using mailer.  If body_filter is not None, then use
        it to filter the lines that are intended for the email
        body."""

        # The sha1s of commits that were introduced by this push.
        # They will be removed from this set as they are processed, to
        # guarantee that one (and only one) email is generated for
        # each new commit.
        unhandled_sha1s = set(self.get_new_commits())
        send_date = IncrementalDateTime()
        for change in self.changes:
            sha1s = []
            for sha1 in reversed(list(self.get_new_commits(change))):
                if sha1 in unhandled_sha1s:
                    sha1s.append(sha1)
                    unhandled_sha1s.remove(sha1)

            # Check if we've got anyone to send to
            if not change.recipients:
                change.environment.log_warning(
                    '*** no recipients configured so no email will be sent\n'
                    '*** for %r update %s->%s\n'
                    % (change.refname, change.old.sha1, change.new.sha1,)
                    )
            else:
                if not change.environment.quiet:
                    change.environment.log_msg(
                        'Sending notification emails to: %s\n' % (change.recipients,))
                extra_values = {'send_date': next(send_date)}

                rev = change.send_single_combined_email(sha1s)
                if rev:
                    mailer.send(
                        change.generate_combined_email(self, rev, body_filter, extra_values),
                        rev.recipients,
                        )
                    # This change is now fully handled; no need to handle
                    # individual revisions any further.
                    continue
                else:
                    mailer.send(
                        change.generate_email(self, body_filter, extra_values),
                        change.recipients,
                        )

            max_emails = change.environment.maxcommitemails
            if max_emails and len(sha1s) > max_emails:
                change.environment.log_warning(
                    '*** Too many new commits (%d), not sending commit emails.\n' % len(sha1s) +
                    '*** Try setting multimailhook.maxCommitEmails to a greater value\n' +
                    '*** Currently, multimailhook.maxCommitEmails=%d\n' % max_emails
                    )
                return

            for (num, sha1) in enumerate(sha1s):
                rev = Revision(change, GitObject(sha1), num=num + 1, tot=len(sha1s))
                if not rev.recipients and rev.cc_recipients:
                    change.environment.log_msg('*** Replacing Cc: with To:\n')
                    rev.recipients = rev.cc_recipients
                    rev.cc_recipients = None
                if rev.recipients:
                    extra_values = {'send_date': next(send_date)}
                    mailer.send(
                        rev.generate_email(self, body_filter, extra_values),
                        rev.recipients,
                        )

        # Consistency check:
        if unhandled_sha1s:
            change.environment.log_error(
                'ERROR: No emails were sent for the following new commits:\n'
                '    %s\n'
                % ('\n    '.join(sorted(unhandled_sha1s)),)
                )


def include_ref(refname, ref_filter_regex, is_inclusion_filter):
    does_match = bool(ref_filter_regex.search(refname))
    if is_inclusion_filter:
        return does_match
    else:  # exclusion filter -- we include the ref if the regex doesn't match
        return not does_match


def run_as_post_receive_hook(environment, mailer):
    ref_filter_regex, is_inclusion_filter = environment.get_ref_filter_regex(True)
    changes = []
    for line in sys.stdin:
        (oldrev, newrev, refname) = line.strip().split(' ', 2)
        if not include_ref(refname, ref_filter_regex, is_inclusion_filter):
            continue
        changes.append(
            ReferenceChange.create(environment, oldrev, newrev, refname)
            )
    if changes:
        push = Push(environment, changes)
        push.send_emails(mailer, body_filter=environment.filter_body)
    if hasattr(mailer, '__del__'):
        mailer.__del__()


def run_as_update_hook(environment, mailer, refname, oldrev, newrev, force_send=False):
    ref_filter_regex, is_inclusion_filter = environment.get_ref_filter_regex(True)
    if not include_ref(refname, ref_filter_regex, is_inclusion_filter):
        return
    changes = [
        ReferenceChange.create(
            environment,
            read_git_output(['rev-parse', '--verify', oldrev]),
            read_git_output(['rev-parse', '--verify', newrev]),
            refname,
            ),
        ]
    push = Push(environment, changes, force_send)
    push.send_emails(mailer, body_filter=environment.filter_body)
    if hasattr(mailer, '__del__'):
        mailer.__del__()


def choose_mailer(config, environment):
    mailer = config.get('mailer', default='sendmail')

    if mailer == 'smtp':
        smtpserver = config.get('smtpserver', default='localhost')
        smtpservertimeout = float(config.get('smtpservertimeout', default=10.0))
        smtpserverdebuglevel = int(config.get('smtpserverdebuglevel', default=0))
        smtpencryption = config.get('smtpencryption', default='none')
        smtpuser = config.get('smtpuser', default='')
        smtppass = config.get('smtppass', default='')
        smtpcacerts = config.get('smtpcacerts', default='')
        mailer = SMTPMailer(
            envelopesender=(environment.get_sender() or environment.get_fromaddr()),
            smtpserver=smtpserver, smtpservertimeout=smtpservertimeout,
            smtpserverdebuglevel=smtpserverdebuglevel,
            smtpencryption=smtpencryption,
            smtpuser=smtpuser,
            smtppass=smtppass,
            smtpcacerts=smtpcacerts
            )
    elif mailer == 'sendmail':
        command = config.get('sendmailcommand')
        if command:
            command = shlex.split(command)
        mailer = SendMailer(command=command, envelopesender=environment.get_sender())
    else:
        environment.log_error(
            'fatal: multimailhook.mailer is set to an incorrect value: "%s"\n' % mailer +
            'please use one of "smtp" or "sendmail".\n'
            )
        sys.exit(1)
    return mailer


KNOWN_ENVIRONMENTS = {
    'generic': GenericEnvironmentMixin,
    'gitolite': GitoliteEnvironmentMixin,
    'stash': StashEnvironmentMixin,
    'gerrit': GerritEnvironmentMixin,
    }


def choose_environment(config, osenv=None, env=None, recipients=None,
                       hook_info=None):
    if not osenv:
        osenv = os.environ

    environment_mixins = [
        ConfigRefFilterEnvironmentMixin,
        ProjectdescEnvironmentMixin,
        ConfigMaxlinesEnvironmentMixin,
        ComputeFQDNEnvironmentMixin,
        ConfigFilterLinesEnvironmentMixin,
        PusherDomainEnvironmentMixin,
        ConfigOptionsEnvironmentMixin,
        ]
    environment_kw = {
        'osenv': osenv,
        'config': config,
        }

    if not env:
        env = config.get('environment')

    if not env:
        if 'GL_USER' in osenv and 'GL_REPO' in osenv:
            env = 'gitolite'
        else:
            env = 'generic'

    environment_mixins.insert(0, KNOWN_ENVIRONMENTS[env])

    if env == 'stash':
        environment_kw['user'] = hook_info['stash_user']
        environment_kw['repo'] = hook_info['stash_repo']
    elif env == 'gerrit':
        environment_kw['project'] = hook_info['project']
        environment_kw['submitter'] = hook_info['submitter']
        environment_kw['update_method'] = hook_info['update_method']

    if recipients:
        environment_mixins.insert(0, StaticRecipientsEnvironmentMixin)
        environment_kw['refchange_recipients'] = recipients
        environment_kw['announce_recipients'] = recipients
        environment_kw['revision_recipients'] = recipients
        environment_kw['scancommitforcc'] = config.get('scancommitforcc')
    else:
        environment_mixins.insert(0, ConfigRecipientsEnvironmentMixin)

    environment_klass = type(
        'EffectiveEnvironment',
        tuple(environment_mixins) + (Environment,),
        {},
        )
    return environment_klass(**environment_kw)


def get_version():
    oldcwd = os.getcwd()
    try:
        try:
            os.chdir(os.path.dirname(os.path.realpath(__file__)))
            git_version = read_git_output(['describe', '--tags', 'HEAD'])
            if git_version == __version__:
                return git_version
            else:
                return '%s (%s)' % (__version__, git_version)
        except:
            pass
    finally:
        os.chdir(oldcwd)
    return __version__


def compute_gerrit_options(options, args, required_gerrit_options):
    if None in required_gerrit_options:
        raise SystemExit("Error: Specify all of --oldrev, --newrev, --refname, "
                         "and --project; or none of them.")

    if options.environment not in (None, 'gerrit'):
        raise SystemExit("Non-gerrit environments incompatible with --oldrev, "
                         "--newrev, --refname, and --project")
    options.environment = 'gerrit'

    if args:
        raise SystemExit("Error: Positional parameters not allowed with "
                         "--oldrev, --newrev, and --refname.")

    # Gerrit oddly omits 'refs/heads/' in the refname when calling
    # ref-updated hook; put it back.
    git_dir = get_git_dir()
    if (not os.path.exists(os.path.join(git_dir, options.refname)) and
        os.path.exists(os.path.join(git_dir, 'refs', 'heads',
                                    options.refname))):
        options.refname = 'refs/heads/' + options.refname

    # Convert each string option unicode for Python3.
    if PYTHON3:
        opts = ['environment', 'recipients', 'oldrev', 'newrev', 'refname',
                'project', 'submitter', 'stash-user', 'stash-repo']
        for opt in opts:
            if not hasattr(options, opt):
                continue
            obj = getattr(options, opt)
            if obj:
                enc = obj.encode('utf-8', 'surrogateescape')
                dec = enc.decode('utf-8', 'replace')
                setattr(options, opt, dec)

    # New revisions can appear in a gerrit repository either due to someone
    # pushing directly (in which case options.submitter will be set), or they
    # can press "Submit this patchset" in the web UI for some CR (in which
    # case options.submitter will not be set and gerrit will not have provided
    # us the information about who pressed the button).
    #
    # Note for the nit-picky: I'm lumping in REST API calls and the ssh
    # gerrit review command in with "Submit this patchset" button, since they
    # have the same effect.
    if options.submitter:
        update_method = 'pushed'
        # The submitter argument is almost an RFC 2822 email address; change it
        # from 'User Name (email@domain)' to 'User Name <email@domain>' so it is
        options.submitter = options.submitter.replace('(', '<').replace(')', '>')
    else:
        update_method = 'submitted'
        # Gerrit knew who submitted this patchset, but threw that information
        # away when it invoked this hook.  However, *IF* Gerrit created a
        # merge to bring the patchset in (project 'Submit Type' is either
        # "Always Merge", or is "Merge if Necessary" and happens to be
        # necessary for this particular CR), then it will have the committer
        # of that merge be 'Gerrit Code Review' and the author will be the
        # person who requested the submission of the CR.  Since this is fairly
        # likely for most gerrit installations (of a reasonable size), it's
        # worth the extra effort to try to determine the actual submitter.
        rev_info = read_git_lines(['log', '--no-walk', '--merges',
                                   '--format=%cN%n%aN <%aE>', options.newrev])
        if rev_info and rev_info[0] == 'Gerrit Code Review':
            options.submitter = rev_info[1]

    # We pass back refname, oldrev, newrev as args because then the
    # gerrit ref-updated hook is much like the git update hook
    return (options,
            [options.refname, options.oldrev, options.newrev],
            {'project': options.project, 'submitter': options.submitter,
             'update_method': update_method})


def check_hook_specific_args(options, args):
    # First check for stash arguments
    if (options.stash_user is None) != (options.stash_repo is None):
        raise SystemExit("Error: Specify both of --stash-user and "
                         "--stash-repo or neither.")
    if options.stash_user:
        options.environment = 'stash'
        return options, args, {'stash_user': options.stash_user,
                               'stash_repo': options.stash_repo}

    # Finally, check for gerrit specific arguments
    required_gerrit_options = (options.oldrev, options.newrev, options.refname,
                               options.project)
    if required_gerrit_options != (None,) * 4:
        return compute_gerrit_options(options, args, required_gerrit_options)

    # No special options in use, just return what we started with
    return options, args, {}


def main(args):
    parser = optparse.OptionParser(
        description=__doc__,
        usage='%prog [OPTIONS]\n   or: %prog [OPTIONS] REFNAME OLDREV NEWREV',
        )

    parser.add_option(
        '--environment', '--env', action='store', type='choice',
        choices=list(KNOWN_ENVIRONMENTS.keys()), default=None,
        help=(
            'Choose type of environment is in use.  Default is taken from '
            'multimailhook.environment if set; otherwise "generic".'
            ),
        )
    parser.add_option(
        '--stdout', action='store_true', default=False,
        help='Output emails to stdout rather than sending them.',
        )
    parser.add_option(
        '--recipients', action='store', default=None,
        help='Set list of email recipients for all types of emails.',
        )
    parser.add_option(
        '--show-env', action='store_true', default=False,
        help=(
            'Write to stderr the values determined for the environment '
            '(intended for debugging purposes).'
            ),
        )
    parser.add_option(
        '--force-send', action='store_true', default=False,
        help=(
            'Force sending refchange email when using as an update hook. '
            'This is useful to work around the unreliable new commits '
            'detection in this mode.'
            ),
        )
    parser.add_option(
        '-c', metavar="<name>=<value>", action='append',
        help=(
            'Pass a configuration parameter through to git.  The value given '
            'will override values from configuration files.  See the -c option '
            'of git(1) for more details.  (Only works with git >= 1.7.3)'
            ),
        )
    parser.add_option(
        '--version', '-v', action='store_true', default=False,
        help=(
            "Display git-multimail's version"
            ),
        )
    # The following options permit this script to be run as a gerrit
    # ref-updated hook.  See e.g.
    # code.google.com/p/gerrit/source/browse/Documentation/config-hooks.txt
    # We suppress help for these items, since these are specific to gerrit,
    # and we don't want users directly using them any way other than how the
    # gerrit ref-updated hook is called.
    parser.add_option('--oldrev', action='store', help=optparse.SUPPRESS_HELP)
    parser.add_option('--newrev', action='store', help=optparse.SUPPRESS_HELP)
    parser.add_option('--refname', action='store', help=optparse.SUPPRESS_HELP)
    parser.add_option('--project', action='store', help=optparse.SUPPRESS_HELP)
    parser.add_option('--submitter', action='store', help=optparse.SUPPRESS_HELP)

    # The following allow this to be run as a stash asynchronous post-receive
    # hook (almost identical to a git post-receive hook but triggered also for
    # merges of pull requests from the UI).  We suppress help for these items,
    # since these are specific to stash.
    parser.add_option('--stash-user', action='store', help=optparse.SUPPRESS_HELP)
    parser.add_option('--stash-repo', action='store', help=optparse.SUPPRESS_HELP)

    (options, args) = parser.parse_args(args)
    (options, args, hook_info) = check_hook_specific_args(options, args)

    if options.version:
        sys.stdout.write('git-multimail version ' + get_version() + '\n')
        return

    if options.c:
        Config.add_config_parameters(options.c)

    config = Config('multimailhook')

    try:
        environment = choose_environment(
            config, osenv=os.environ,
            env=options.environment,
            recipients=options.recipients,
            hook_info=hook_info,
            )

        if options.show_env:
            sys.stderr.write('Environment values:\n')
            for (k, v) in sorted(environment.get_values().items()):
                sys.stderr.write('    %s : %r\n' % (k, v))
            sys.stderr.write('\n')

        if options.stdout or environment.stdout:
            mailer = OutputMailer(sys.stdout)
        else:
            mailer = choose_mailer(config, environment)

        # Dual mode: if arguments were specified on the command line, run
        # like an update hook; otherwise, run as a post-receive hook.
        if args:
            if len(args) != 3:
                parser.error('Need zero or three non-option arguments')
            (refname, oldrev, newrev) = args
            run_as_update_hook(environment, mailer, refname, oldrev, newrev, options.force_send)
        else:
            run_as_post_receive_hook(environment, mailer)
    except ConfigurationException:
        sys.exit(sys.exc_info()[1])
    except Exception:
        t, e, tb = sys.exc_info()
        import traceback
        sys.stdout.write('\n')
        sys.stdout.write('Exception \'' + t.__name__ +
                         '\' raised. Please report this as a bug to\n')
        sys.stdout.write('https://github.com/git-multimail/git-multimail/issues\n')
        sys.stdout.write('with the information below:\n\n')
        sys.stdout.write('git-multimail version ' + get_version() + '\n')
        sys.stdout.write('Python version ' + sys.version + '\n')
        traceback.print_exc(file=sys.stdout)
        sys.exit(1)

if __name__ == '__main__':
    main(sys.argv[1:])
