#! /usr/bin/env python

__version__ = '1.4.0'

# Copyright (c) 2015-2016 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 logging
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, errors='strict'):
        return s.decode(ENCODING, errors)

    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))

    def read_line(f):
        # Try reading with the default encoding. If it fails,
        # try UTF-8.
        out = f.buffer.readline()
        try:
            return out.decode(sys.getdefaultencoding())
        except UnicodeEncodeError:
            return out.decode(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, errors='strict'):
        return s

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

    def read_line(f):
        return f.readline()

    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 "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" 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 "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" 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 "add" were already present in the repository and have only
been added to this reference.

"""


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


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

    from %(oldrev_short)-8s (%(oldrev_type)s)
      to %(newrev_short)-8s (%(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)8s %(rev_short)-8s %(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
    errors = 'strict'
    if 'errors' in kw:
        errors = kw['errors']
        del kw['errors']
    p = subprocess.Popen(
        tuple(str_to_bytes(w) for w in cmd),
        stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kw
        )
    (out, err) = p.communicate(input)
    out = bytes_to_str(out, errors=errors)
    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_specific_fromaddr(self):
        """For kinds of Changes which specify it, return the kind-specific
        From address to use."""
        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' % (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]
            )

        max_subject_length = self.environment.get_max_subject_length()
        if max_subject_length > 0 and len(oneline) > max_subject_length:
            oneline = oneline[:max_subject_length - 6] + ' [...]'

        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,
                errors='replace'):
            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_specific_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.'
                    % (refname,)
                    )
                klass = OtherReferenceChange
            else:
                # Some other reference namespace:
                environment.log_warning(
                    '*** Push-update of strange reference %r\n'
                    '***  - incomplete email generated.'
                    % (refname,)
                    )
                klass = OtherReferenceChange
        else:
            # Anything else (is there anything else?)
            environment.log_warning(
                '*** Unknown type of update to %r (%s)\n'
                '***  - incomplete email generated.'
                % (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 = 'discard'
                    else:
                        action = 'omit'
                    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 = 'add'
                    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 = 'discard'
                    else:
                        action = 'omit'
                    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 = 'add'
                    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='discard', 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_specific_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

        def revision_gen_link(base_url):
            # revision is used only to generate the body, and
            # _content_type is set while generating headers. Get it
            # from the BranchChange object.
            revision._content_type = self._content_type
            return revision.generate_browse_link(base_url)
        self.generate_browse_link = revision_gen_link
        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 '      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 __init__(self, environment):
        self.environment = environment

    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, environment, 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'."""
        super(SendMailer, self).__init__(environment)
        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:
            self.environment.get_logger().error(
                '*** 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:
            self.environment.get_logger().error(
                '*** Error while generating commit email\n'
                '***  - mail sending aborted.\n'
                )
            if hasattr(p, 'terminate'):
                # subprocess.terminate() is not available in Python 2.4
                p.terminate()
            else:
                import signal
                os.kill(p.pid, signal.SIGTERM)
            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, environment,
                 envelopesender, smtpserver,
                 smtpservertimeout=10.0, smtpserverdebuglevel=0,
                 smtpencryption='none',
                 smtpuser='', smtppass='',
                 smtpcacerts=''
                 ):
        super(SMTPMailer, self).__init__(environment)
        if not envelopesender:
            self.environment.get_logger().error(
                '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:
                    self.environment.get_logger().error(
                        '*** 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
                        )
                    self.environment.get_logger().error(
                        '*** 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:
            self.environment.get_logger().error(
                '*** Error establishing SMTP connection to %s ***\n'
                '*** %s\n'
                % (self.smtpserver, 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:
            err = sys.exc_info()[1]
            self.environment.get_logger().error(
                '*** Error sending email ***\n'
                '*** 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:
                self.environment.get_logger().error(
                    '*** Error closing the SMTP connection ***\n'
                    '*** Exiting anyway ... ***\n'
                    '*** %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/".

        get_max_subject_length()

            Return an int giving the maximal length for the subject
            (git log --oneline).

    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.

        log_file, error_log_file, debug_log_file (string)

            Name of a file to which logs should be sent.

        verbose (int)

            How verbose the system should be.
            - 0 (default): show info, errors, ...
            - 1 : show basic debug info
    """

    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.logger = None

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

        self._values = None

    def get_logger(self):
        """Get (possibly creates) the logger associated to this environment."""
        if self.logger is None:
            self.logger = Logger(self)
        return self.logger

    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 get_max_subject_length(self):
        """Return the maximal subject line (git log --oneline) length.
        Longer subject lines will be truncated."""
        raise NotImplementedError()

    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."""
        self.get_logger().info(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."""
        self.get_logger().warning(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."""
        self.get_logger().error(msg)

    def check(self):
        pass


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

        self.log_file = config.get('logFile', default=None)
        self.error_log_file = config.get('errorLogFile', default=None)
        self.debug_log_file = config.get('debugLogFile', default=None)
        if config.get_bool('Verbose', default=False):
            self.verbose = 1
        else:
            self.verbose = 0

    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:
                emailprefix += ' '
        else:
            emailprefix = '[%(repo_shortname)s] '
        short_name = self.get_repo_shortname()
        try:
            return emailprefix % {'repo_shortname': short_name}
        except:
            self.get_logger().error(
                '*** Invalid multimailhook.emailPrefix: %s\n' % emailprefix +
                '*** %s\n' % sys.exc_info()[1] +
                "*** Only the '%(repo_shortname)s' placeholder is allowed\n"
                )
            raise ConfigurationException(
                '"%s" is not an allowed setting for emailPrefix' % emailprefix
                )

    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:
            specific_fromaddr = change.get_specific_fromaddr()
            if specific_fromaddr:
                fromaddr = specific_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.

        email_max_line_length (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,
                 email_max_line_length=500, max_subject_length=500,
                 **kw):
        super(FilterLinesEnvironmentMixin, self).__init__(**kw)
        self.__strict_utf8 = strict_utf8
        self.__email_max_line_length = email_max_line_length
        self.__max_subject_length = max_subject_length

    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.__email_max_line_length > 0:
                lines = limit_linelength(lines, self.__email_max_line_length)
            if not PYTHON3:
                lines = (line.encode(ENCODING, 'replace') for line in lines)
        elif self.__email_max_line_length:
            lines = limit_linelength(lines, self.__email_max_line_length)

        return lines

    def get_max_subject_length(self):
        return self.__max_subject_length


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

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

        max_subject_length = config.get('subjectMaxLength', default=email_max_line_length)
        if max_subject_length is not None:
            kw['max_subject_length'] = int(max_subject_length)

        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 > 0:
            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:
        self.__refchange_recipients = refchange_recipients
        self.__announce_recipients = announce_recipients
        self.__revision_recipients = revision_recipients

    def check(self):
        if not (self.get_refchange_recipients(None) or
                self.get_announce_recipients(None) or
                self.get_revision_recipients(None) or
                self.get_scancommitforcc()):
            raise ConfigurationException('No email recipients configured!')
        super(StaticRecipientsEnvironmentMixin, self).check()

    def get_refchange_recipients(self, refchange):
        if self.__refchange_recipients is None:
            return super(StaticRecipientsEnvironmentMixin,
                         self).get_refchange_recipients(refchange)
        return self.__refchange_recipients

    def get_announce_recipients(self, annotated_tag_change):
        if self.__announce_recipients is None:
            return super(StaticRecipientsEnvironmentMixin,
                         self).get_refchange_recipients(annotated_tag_change)
        return self.__announce_recipients

    def get_revision_recipients(self, revision):
        if self.__revision_recipients is None:
            return super(StaticRecipientsEnvironmentMixin,
                         self).get_refchange_recipients(revision)
        return self.__revision_recipients


class CLIRecipientsEnvironmentMixin(Environment):
    """Mixin storing recipients information coming from the
    command-line."""

    def __init__(self, cli_recipients=None, **kw):
        super(CLIRecipientsEnvironmentMixin, self).__init__(**kw)
        self.__cli_recipients = cli_recipients

    def get_refchange_recipients(self, refchange):
        if self.__cli_recipients is None:
            return super(CLIRecipientsEnvironmentMixin,
                         self).get_refchange_recipients(refchange)
        return self.__cli_recipients

    def get_announce_recipients(self, annotated_tag_change):
        if self.__cli_recipients is None:
            return super(CLIRecipientsEnvironmentMixin,
                         self).get_announce_recipients(annotated_tag_change)
        return self.__cli_recipients

    def get_revision_recipients(self, revision):
        if self.__cli_recipients is None:
            return super(CLIRecipientsEnvironmentMixin,
                         self).get_revision_recipients(revision)
        return self.__cli_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.")
        self.__is_do_send_filter = bool(ref_filter_do_send_regex)
        if ref_filter_do_send_regex:
            ref_filter_send_regex = ref_filter_do_send_regex
        elif ref_filter_dont_send_regex:
            ref_filter_send_regex = ref_filter_dont_send_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]))

    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 GitoliteEnvironmentHighPrecMixin(Environment):
    def get_pusher(self):
        return self.osenv.get('GL_USER', 'unknown user')


class GitoliteEnvironmentLowPrecMixin(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(GitoliteEnvironmentLowPrecMixin, self).get_repo_shortname()
            )

    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(GitoliteEnvironmentLowPrecMixin, 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 StashEnvironmentHighPrecMixin(Environment):
    def __init__(self, user=None, repo=None, **kw):
        super(StashEnvironmentHighPrecMixin,
              self).__init__(user=user, repo=repo, **kw)
        self.__user = user
        self.__repo = repo

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

    def get_pusher_email(self):
        return self.__user


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

    def get_repo_shortname(self):
        return self.__repo

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


class GerritEnvironmentHighPrecMixin(Environment):
    def __init__(self, project=None, submitter=None, update_method=None, **kw):
        super(GerritEnvironmentHighPrecMixin,
              self).__init__(submitter=submitter, project=project, **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_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(GerritEnvironmentHighPrecMixin, self).get_pusher_email()

    def get_default_ref_ignore_regex(self):
        default = super(GerritEnvironmentHighPrecMixin, 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(GerritEnvironmentHighPrecMixin, self).get_revision_recipients(revision)

    def get_update_method(self):
        return self.__update_method


class GerritEnvironmentLowPrecMixin(Environment):
    def __init__(self, project=None, submitter=None, **kw):
        super(GerritEnvironmentLowPrecMixin, self).__init__(**kw)
        self.__project = project
        self.__submitter = submitter

    def get_repo_shortname(self):
        return self.__project

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


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'
                    % (change.refname, change.old.sha1, change.new.sha1,)
                    )
            else:
                if not change.environment.quiet:
                    change.environment.log_msg(
                        'Sending notification emails to: %s' % (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' % 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:')
                    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    '.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):
    environment.check()
    send_filter_regex, send_is_inclusion_filter = environment.get_ref_filter_regex(True)
    ref_filter_regex, is_inclusion_filter = environment.get_ref_filter_regex(False)
    changes = []
    while True:
        line = read_line(sys.stdin)
        if line == '':
            break
        (oldrev, newrev, refname) = line.strip().split(' ', 2)
        environment.get_logger().debug(
            "run_as_post_receive_hook: oldrev=%s, newrev=%s, refname=%s" %
            (oldrev, newrev, refname))

        if not include_ref(refname, ref_filter_regex, is_inclusion_filter):
            continue
        if not include_ref(refname, send_filter_regex, send_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):
    environment.check()
    send_filter_regex, send_is_inclusion_filter = environment.get_ref_filter_regex(True)
    ref_filter_regex, is_inclusion_filter = environment.get_ref_filter_regex(False)
    if not include_ref(refname, ref_filter_regex, is_inclusion_filter):
        return
    if not include_ref(refname, send_filter_regex, send_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 check_ref_filter(environment):
    send_filter_regex, send_is_inclusion = environment.get_ref_filter_regex(True)
    ref_filter_regex, ref_is_inclusion = environment.get_ref_filter_regex(False)

    def inc_exc_lusion(b):
        if b:
            return 'inclusion'
        else:
            return 'exclusion'

    if send_filter_regex:
        sys.stdout.write("DoSend/DontSend filter regex (" +
                         (inc_exc_lusion(send_is_inclusion)) +
                         '): ' + send_filter_regex.pattern +
                         '\n')
    if send_filter_regex:
        sys.stdout.write("Include/Exclude filter regex (" +
                         (inc_exc_lusion(ref_is_inclusion)) +
                         '): ' + ref_filter_regex.pattern +
                         '\n')
    sys.stdout.write(os.linesep)

    sys.stdout.write(
        "Refs marked as EXCLUDE are excluded by either refFilterInclusionRegex\n"
        "or refFilterExclusionRegex. No emails will be sent for commits included\n"
        "in these refs.\n"
        "Refs marked as DONT-SEND are excluded by either refFilterDoSendRegex or\n"
        "refFilterDontSendRegex, but not by either refFilterInclusionRegex or\n"
        "refFilterExclusionRegex. Emails will be sent for commits included in these\n"
        "refs only when the commit reaches a ref which isn't excluded.\n"
        "Refs marked as DO-SEND are not excluded by any filter. Emails will\n"
        "be sent normally for commits included in these refs.\n")

    sys.stdout.write(os.linesep)

    for refname in read_git_lines(['for-each-ref', '--format', '%(refname)']):
        sys.stdout.write(refname)
        if not include_ref(refname, ref_filter_regex, ref_is_inclusion):
            sys.stdout.write(' EXCLUDE')
        elif not include_ref(refname, send_filter_regex, send_is_inclusion):
            sys.stdout.write(' DONT-SEND')
        else:
            sys.stdout.write(' DO-SEND')

        sys.stdout.write(os.linesep)


def show_env(environment, out):
    out.write('Environment values:\n')
    for (k, v) in sorted(environment.get_values().items()):
        if k:  # Don't show the {'' : ''} pair.
            out.write('    %s : %r\n' % (k, v))
    out.write('\n')
    # Flush to avoid interleaving with further log output
    out.flush()


def check_setup(environment):
    environment.check()
    show_env(environment, sys.stdout)
    sys.stdout.write("Now, checking that git-multimail's standard input "
                     "is properly set ..." + os.linesep)
    sys.stdout.write("Please type some text and then press Return" + os.linesep)
    stdin = sys.stdin.readline()
    sys.stdout.write("You have just entered:" + os.linesep)
    sys.stdout.write(stdin)
    sys.stdout.write("git-multimail seems properly set up." + os.linesep)


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(
            environment,
            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(environment,
                            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".'
            )
        sys.exit(1)
    return mailer


KNOWN_ENVIRONMENTS = {
    'generic': {'highprec': GenericEnvironmentMixin},
    'gitolite': {'highprec': GitoliteEnvironmentHighPrecMixin,
                 'lowprec': GitoliteEnvironmentLowPrecMixin},
    'stash': {'highprec': StashEnvironmentHighPrecMixin,
              'lowprec': StashEnvironmentLowPrecMixin},
    'gerrit': {'highprec': GerritEnvironmentHighPrecMixin,
               'lowprec': GerritEnvironmentLowPrecMixin},
    }


def choose_environment(config, osenv=None, env=None, recipients=None,
                       hook_info=None):
    env_name = choose_environment_name(config, env, osenv)
    environment_klass = build_environment_klass(env_name)
    env = build_environment(environment_klass, env_name, config,
                            osenv, recipients, hook_info)
    return env


def choose_environment_name(config, env, osenv):
    if not osenv:
        osenv = os.environ

    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'
    return env


COMMON_ENVIRONMENT_MIXINS = [
    ConfigRecipientsEnvironmentMixin,
    CLIRecipientsEnvironmentMixin,
    ConfigRefFilterEnvironmentMixin,
    ProjectdescEnvironmentMixin,
    ConfigMaxlinesEnvironmentMixin,
    ComputeFQDNEnvironmentMixin,
    ConfigFilterLinesEnvironmentMixin,
    PusherDomainEnvironmentMixin,
    ConfigOptionsEnvironmentMixin,
    ]


def build_environment_klass(env_name):
    if 'class' in KNOWN_ENVIRONMENTS[env_name]:
        return KNOWN_ENVIRONMENTS[env_name]['class']

    environment_mixins = []
    known_env = KNOWN_ENVIRONMENTS[env_name]
    if 'highprec' in known_env:
        high_prec_mixin = known_env['highprec']
        environment_mixins.append(high_prec_mixin)
    environment_mixins = environment_mixins + COMMON_ENVIRONMENT_MIXINS
    if 'lowprec' in known_env:
        low_prec_mixin = known_env['lowprec']
        environment_mixins.append(low_prec_mixin)
    environment_mixins.append(Environment)
    klass_name = env_name.capitalize() + 'Environement'
    environment_klass = type(
        klass_name,
        tuple(environment_mixins),
        {},
        )
    KNOWN_ENVIRONMENTS[env_name]['class'] = environment_klass
    return environment_klass


GerritEnvironment = build_environment_klass('gerrit')
StashEnvironment = build_environment_klass('stash')
GitoliteEnvironment = build_environment_klass('gitolite')
GenericEnvironment = build_environment_klass('generic')


def build_environment(environment_klass, env, config,
                      osenv, recipients, hook_info):
    environment_kw = {
        'osenv': osenv,
        'config': config,
        }

    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']

    environment_kw['cli_recipients'] = recipients

    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,
                           raw_refname):
    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, raw_refname)) and
        os.path.exists(os.path.join(git_dir, 'refs', 'heads',
                                    raw_refname))):
        options.refname = 'refs/heads/' + options.refname

    # 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):
    raw_refname = 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)

    # 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,
                                      raw_refname)

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


class Logger(object):
    def parse_verbose(self, verbose):
        if verbose > 0:
            return logging.DEBUG
        else:
            return logging.INFO

    def create_log_file(self, environment, name, path, verbosity):
        log_file = logging.getLogger(name)
        file_handler = logging.FileHandler(path)
        log_fmt = logging.Formatter("%(asctime)s [%(levelname)-5.5s]  %(message)s")
        file_handler.setFormatter(log_fmt)
        log_file.addHandler(file_handler)
        log_file.setLevel(verbosity)
        return log_file

    def __init__(self, environment):
        self.environment = environment
        self.loggers = []
        stderr_log = logging.getLogger('git_multimail.stderr')

        class EncodedStderr(object):
            def write(self, x):
                write_str(sys.stderr, x)

            def flush(self):
                sys.stderr.flush()

        stderr_handler = logging.StreamHandler(EncodedStderr())
        stderr_log.addHandler(stderr_handler)
        stderr_log.setLevel(self.parse_verbose(environment.verbose))
        self.loggers.append(stderr_log)

        if environment.debug_log_file is not None:
            debug_log_file = self.create_log_file(
                environment, 'git_multimail.debug', environment.debug_log_file, logging.DEBUG)
            self.loggers.append(debug_log_file)

        if environment.log_file is not None:
            log_file = self.create_log_file(
                environment, 'git_multimail.file', environment.log_file, logging.INFO)
            self.loggers.append(log_file)

        if environment.error_log_file is not None:
            error_log_file = self.create_log_file(
                environment, 'git_multimail.error', environment.error_log_file, logging.ERROR)
            self.loggers.append(error_log_file)

    def info(self, msg):
        for l in self.loggers:
            l.info(msg)

    def debug(self, msg):
        for l in self.loggers:
            l.debug(msg)

    def warning(self, msg):
        for l in self.loggers:
            l.warning(msg)

    def error(self, msg):
        for l in self.loggers:
            l.error(msg)


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), then proceed normally.'
            ),
        )
    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"
            ),
        )

    parser.add_option(
        '--python-version', action='store_true', default=False,
        help=(
            "Display the version of Python used by git-multimail"
            ),
        )

    parser.add_option(
        '--check-ref-filter', action='store_true', default=False,
        help=(
            'List refs and show information on how git-multimail '
            'will process them.'
            )
        )

    # 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.python_version:
        sys.stdout.write('Python version ' + sys.version + '\n')
        return

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

    config = Config('multimailhook')

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

        if options.show_env:
            show_env(environment, sys.stderr)

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

        must_check_setup = os.environ.get('GIT_MULTIMAIL_CHECK_SETUP')
        if must_check_setup == '':
            must_check_setup = False
        if options.check_ref_filter:
            check_ref_filter(environment)
        elif must_check_setup:
            check_setup(environment)
        # Dual mode: if arguments were specified on the command line, run
        # like an update hook; otherwise, run as a post-receive hook.
        elif args:
            if len(args) != 3:
                parser.error('Need zero or three non-option arguments')
            (refname, oldrev, newrev) = args
            environment.get_logger().debug(
                "run_as_update_hook: refname=%s, oldrev=%s, newrev=%s, force_send=%s" %
                (refname, oldrev, newrev, options.force_send))
            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 SystemExit:
        raise
    except Exception:
        t, e, tb = sys.exc_info()
        import traceback
        sys.stderr.write('\n')  # Avoid mixing message with previous output
        msg = (
            'Exception \'' + t.__name__ +
            '\' raised. Please report this as a bug to\n'
            'https://github.com/git-multimail/git-multimail/issues\n'
            'with the information below:\n\n'
            'git-multimail version ' + get_version() + '\n'
            'Python version ' + sys.version + '\n' +
            traceback.format_exc())
        try:
            environment.get_logger().error(msg)
        except:
            sys.stderr.write(msg)
        sys.exit(1)

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