#! /usr/bin/env python

__version__ = '1.5.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 uuid
import base64

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

    import html

    def html_escape(s):
        return html.escape(s)

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

    import cgi

    def html_escape(s):
        return cgi.escape(s, True)

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
Thread-Index: %(thread_index)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
Thread-Index: %(thread_index)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 __ne__(self, other):
        return not self == other

    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] = html_escape(values[k])
        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, push):
        """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 html_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 = html_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)

        # -s is short for --no-patch, but -s works on older git's (e.g. 1.7)
        self.parents = read_git_lines(['show', '-s', '--format=%P',
                                      self.rev.sha1])[0].split()

        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['parents'] = ' '.join(self.parents)
        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['thread_index'] = self.reference_change.thread_index
        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,
            )

    @staticmethod
    def make_thread_index():
        """Return a string appropriate for the Thread-Index header,
        needed by MS Outlook to get threading right.

        The format is (base64-encoded):
        - 1 byte must be 1
        - 5 bytes encode a date (hardcoded here)
        - 16 bytes for a globally unique identifier

        FIXME: Unfortunately, even with the Thread-Index field, MS
        Outlook doesn't seem to do the threading reliably (see
        https://github.com/git-multimail/git-multimail/pull/194).
        """
        thread_index = b'\x01\x00\x00\x12\x34\x56' + uuid.uuid4().bytes
        return base64.standard_b64encode(thread_index).decode('ascii')

    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.thread_index = self.make_thread_index()
        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['thread_index'] = self.thread_index
        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 close(self):
        pass

    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
        self.loggedin = False
        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 access 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 certificate 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 close(self):
        if hasattr(self, 'smtp'):
            self.smtp.quit()
            del self.smtp

    def __del__(self):
        self.close()

    def send(self, lines, to_addrs):
        try:
            if self.username or self.password:
                if not self.loggedin:
                    self.smtp.login(self.username, self.password)
                    self.loggedin = True
            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 socket.timeout:
            self.environment.get_logger().error(
                '*** Error sending email ***\n'
                '*** SMTP server timed out (timeout is %s)\n'
                % self.smtpservertimeout)
        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, environment=None):
        super(OutputMailer, self).__init__(environment=environment)
        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.excludemergerevisions = False
        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')

        self.excludemergerevisions = config.get('excludeMergeRevisions')

        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 description 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(
        ConfigEnvironmentMixin,
        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()
            )

    @staticmethod
    def _compile_regex(re_template):
        return (
            re.compile(re_template % x)
            for x in (
                r'BEGIN\s+USER\s+EMAILS',
                r'([^\s]+)\s+(.*)',
                r'END\s+USER\s+EMAILS',
                ))

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

            mailaddress_map = self.config.get('MailaddressMap')
            # If relative, consider relative to GL_CONF:
            if mailaddress_map:
                mailaddress_map = os.path.join(os.path.dirname(GL_CONF),
                                               mailaddress_map)
                if os.path.isfile(mailaddress_map):
                    f = open(mailaddress_map, 'rU')
                    try:
                        # Leading '#' is optional
                        re_begin, re_user, re_end = self._compile_regex(
                            r'^(?:\s*#)?\s*%s\s*$')
                        for l in f:
                            l = l.rstrip('\n')
                            if re_begin.match(l) or re_end.match(l):
                                continue  # Ignore these lines
                            m = re_user.match(l)
                            if m:
                                if m.group(1) == GL_USER:
                                    return m.group(2)
                                else:
                                    continue  # Not this user, but not an error
                            raise ConfigurationException(
                                "Syntax error in mail address map.\n"
                                "Check file {}.\n"
                                "Line: {}".format(mailaddress_map, l))

                    finally:
                        f.close()

            if os.path.isfile(GL_CONF):
                f = open(GL_CONF, 'rU')
                try:
                    in_user_emails_section = False
                    re_begin, re_user, re_end = self._compile_regex(
                        r'^\s*#\s*%s\s*$')
                    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 and m.group(1) == GL_USER:
                            return m.group(2)
                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(r'(.*?)\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(r'(.*?)\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 len(rev.parents) > 1 and change.environment.excludemergerevisions:
                    # skipping a merge commit
                    continue
                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 not changes:
        mailer.close()
        return
    push = Push(environment, changes)
    try:
        push.send_emails(mailer, body_filter=environment.filter_body)
    finally:
        mailer.close()


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,
            ),
        ]
    if not changes:
        mailer.close()
        return
    push = Push(environment, changes, force_send)
    try:
        push.send_emails(mailer, body_filter=environment.filter_body)
    finally:
        mailer.close()


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() + 'Environment'
    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, *args, **kwargs):
        for l in self.loggers:
            l.info(msg, *args, **kwargs)

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

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

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


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, environment)
        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:])
