def __email_ref_update(self):
        """Send the email describing to the reference update.

        This email can be seen as a "cover email", or a quick summary
        of the update that was performed.

        REMARKS
            The hooks may decide that such an email may not be necessary,
            and thus send nothing. See self.get_update_email_contents
            for more details.
        """
        update_email_contents = self.get_update_email_contents()

        if update_email_contents is not None:
            (email_to, subject, body) = update_email_contents
            update_email = Email(self.email_info,
                                 email_to,
                                 subject,
                                 body,
                                 None,
                                 self.ref_name,
                                 self.old_rev,
                                 self.new_rev,
                                 send_to_filer=self.send_cover_email_to_filer)
            update_email.enqueue()
    def email_commit(self, commit):
        """Send an email describing the given commit.

        PARAMETERS
            commit: A CommitInfo object.
        """
        if self.ref_namespace in ('refs/heads', 'refs/tags'):
            if self.short_ref_name == 'master':
                branch = ''
            else:
                branch = '/%s' % self.short_ref_name
        else:
            # Unusual namespace for our reference. Use the reference
            # name in full to label the branch name.
            branch = '(%s)' % self.ref_name

        subject = '[%(repo)s%(branch)s] %(subject)s' % {
            'repo': self.email_info.project_name,
            'branch': branch,
            'subject': commit.subject[:SUBJECT_MAX_SUBJECT_CHARS],
            }

        # Generate the body of the email in two pieces:
        #   1. The commit description without the patch;
        #   2. The diff stat and patch.
        # This allows us to insert our little "Diff:" marker that
        # bugtool detects when parsing the email for filing (this
        # part is now performed by the Email class). The purpose
        # is to prevent bugtool from searching for TNs in the patch
        # itself.
        #
        # For the diff, there is one subtlelty:
        # Git commands calls strip on the output, which is usually
        # a good thing, but not in the case of the diff output.
        # Prevent this from happening by putting an artificial
        # character at the start of the format string, and then
        # by stripping it from the output.

        body = git.log(commit.rev, max_count="1") + '\n'
        if git_config('hooks.commit-url') is not None:
            url_info = {'rev': commit.rev,
                        'ref_name': self.ref_name}
            body = (git_config('hooks.commit-url') % url_info
                    + '\n\n'
                    + body)

        diff = git.show(commit.rev, p=True, M=True, stat=True,
                        pretty="format:|")[1:]

        filer_cmd = git_config('hooks.file-commit-cmd')
        if filer_cmd is not None:
            filer_cmd = shlex.split(filer_cmd)

        email = Email(self.email_info,
                      commit.email_to, subject, body, commit.author,
                      self.ref_name, commit.base_rev_for_display(),
                      commit.rev, diff, filer_cmd=filer_cmd)
        email.enqueue()
Exemple #3
0
    def email_commit(self, commit):
        """See AbstractUpdate.email_commit."""
        notes = GitNotes(commit.rev)

        # Get commit info for the annotated commit
        annotated_commit = commit_info_list("-1", notes.annotated_rev)[0]

        # Get a description of the annotated commit (a la "git show"),
        # except that we do not want the diff.
        #
        # Also, we have to handle the notes manually, as the commands
        # get the notes from the HEAD of the notes/commits branch,
        # whereas what we needs is the contents at the commit.rev.
        # This makes a difference when a single push updates the notes
        # of the same commit multiple times.
        annotated_rev_log = git.log(annotated_commit.rev,
                                    no_notes=True,
                                    max_count="1")
        notes_contents = (None if notes.contents is None else indent(
            notes.contents, ' ' * 4))

        # Determine subject tag based on ref name:
        #   * remove "refs/notes" prefix
        #   * remove entire tag if remaining component is "commits"
        #     (case of the default refs/notes/commits ref)
        notes_ref = self.ref_name.split('/', 2)[2]
        if notes_ref == "commits":
            subject_tag = ""
        else:
            subject_tag = "(%s)" % notes_ref

        subject = '[notes%s][%s] %s' % (subject_tag,
                                        self.email_info.project_name,
                                        annotated_commit.subject)

        body_template = (DELETED_NOTES_COMMIT_EMAIL_BODY_TEMPLATE
                         if notes_contents is None else
                         UPDATED_NOTES_COMMIT_EMAIL_BODY_TEMPLATE)
        body = body_template % {
            'annotated_rev_log': annotated_rev_log,
            'notes_contents': notes_contents,
        }

        # Git commands calls strip on the output, which is usually
        # a good thing, but not in the case of the diff output.
        # Prevent this from happening by putting an artificial
        # character at the start of the format string, and then
        # by stripping it from the output.
        diff = git.show(commit.rev, pretty="format:|", p=True)[1:]

        email_bcc = git_config('hooks.filer-email')

        email = Email(self.email_info,
                      annotated_commit.email_to(self.ref_name), email_bcc,
                      subject, body, commit.author, self.ref_name,
                      commit.base_rev_for_display(), commit.rev, diff)
        email.enqueue()
Exemple #4
0
    def email_commit(self, commit):
        """See AbstractUpdate.email_commit."""
        notes = GitNotes(commit.rev)

        # Create a partial CommitInfo object for the commit that
        # our note annotates.  We create a partial one in order
        # to avoid computing some info we do not need...
        annotated_commit = CommitInfo(notes.annotated_rev, None, None, None)

        # Get a description of the annotated commit (a la "git show"),
        # except that we do not want the diff.
        #
        # Also, we have to handle the notes manually, as the commands
        # get the notes from the HEAD of the notes/commits branch,
        # whereas what we needs is the contents at the commit.rev.
        # This makes a difference when a single push updates the notes
        # of the same commit multiple times.
        annotated_rev_info = git.log(annotated_commit.rev,
                                     no_notes=True,
                                     max_count="1")
        notes_contents = (None if notes.contents is None else indent(
            notes.contents, ' ' * 4))

        subject = '[%s] notes update for %s' % (self.email_info.project_name,
                                                notes.annotated_rev)

        body_template = (DELETED_NOTES_COMMIT_EMAIL_BODY_TEMPLATE
                         if notes_contents is None else
                         UPDATED_NOTES_COMMIT_EMAIL_BODY_TEMPLATE)
        body = body_template % {
            'annotated_rev_info': annotated_rev_info,
            'notes_contents': notes_contents,
        }

        # Git commands calls strip on the output, which is usually
        # a good thing, but not in the case of the diff output.
        # Prevent this from happening by putting an artificial
        # character at the start of the format string, and then
        # by stripping it from the output.
        diff = git.show(commit.rev, pretty="format:|", p=True)[1:]

        email = Email(self.email_info, annotated_commit.email_to, subject,
                      body, commit.author, self.ref_name,
                      commit.base_rev_for_display(), commit.rev, diff)
        email.enqueue()
Exemple #5
0
    def email_commit(self, commit):
        """See AbstractUpdate.email_commit."""
        notes = GitNotes(commit.rev)

        # Create a partial CommitInfo object for the commit that
        # our note annotates.  We create a partial one in order
        # to avoid computing some info we do not need...
        annotated_commit = CommitInfo(notes.annotated_rev, None, None, None)

        # Get a description of the annotated commit (a la "git show"),
        # except that we do not want the diff.
        #
        # Also, we have to handle the notes manually, as the commands
        # get the notes from the HEAD of the notes/commits branch,
        # whereas what we needs is the contents at the commit.rev.
        # This makes a difference when a single push updates the notes
        # of the same commit multiple times.
        annotated_rev_info = git.log(annotated_commit.rev, no_notes=True,
                                     max_count="1")
        notes_contents = (None if notes.contents is None
                          else indent(notes.contents, ' ' * 4))

        subject = '[%s] notes update for %s' % (self.email_info.project_name,
                                                notes.annotated_rev)

        body_template = (
            DELETED_NOTES_COMMIT_EMAIL_BODY_TEMPLATE if notes_contents is None
            else UPDATED_NOTES_COMMIT_EMAIL_BODY_TEMPLATE)
        body = body_template % {
            'annotated_rev_info': annotated_rev_info,
            'notes_contents': notes_contents,
            }

        # Git commands calls strip on the output, which is usually
        # a good thing, but not in the case of the diff output.
        # Prevent this from happening by putting an artificial
        # character at the start of the format string, and then
        # by stripping it from the output.
        diff = git.show(commit.rev, pretty="format:|", p=True)[1:]

        email = Email(self.email_info, annotated_commit.email_to,
                      subject, body, commit.author, self.ref_name,
                      commit.base_rev_for_display(), commit.rev, diff)
        email.enqueue()
    def __email_ref_update(self):
        """Send the email describing to the reference update.

        This email can be seen as a "cover email", or a quick summary
        of the update that was performed.

        REMARKS
            The hooks may decide that such an email may not be necessary,
            and thus send nothing. See self.get_update_email_contents
            for more details.
        """
        update_email_contents = self.get_update_email_contents()

        if update_email_contents is not None:
            (email_to, subject, body) = update_email_contents
            update_email = Email(self.email_info,
                                 email_to, subject, body, None,
                                 self.ref_name, self.old_rev, self.new_rev,
                                 send_to_filer=self.send_cover_email_to_filer)
            update_email.enqueue()
Exemple #7
0
    def email_commit(self, commit):
        """Send an email describing the given commit.

        PARAMETERS
            commit: A CommitInfo object.
        """
        if self.ref_namespace in ('refs/heads', 'refs/tags'):
            if self.short_ref_name == 'master':
                branch = ''
            else:
                branch = '/%s' % self.short_ref_name
        else:
            # Unusual namespace for our reference. Use the reference
            # name in full to label the branch name.
            branch = '(%s)' % self.ref_name

        subject = '[%(repo)s%(branch)s] %(subject)s' % {
            'repo': self.email_info.project_name,
            'branch': branch,
            'subject': commit.subject[:SUBJECT_MAX_SUBJECT_CHARS],
        }

        # Generate the body of the email in two pieces:
        #   1. The commit description without the patch;
        #   2. The diff stat and patch.
        # This allows us to insert our little "Diff:" marker that
        # bugtool detects when parsing the email for filing (this
        # part is now performed by the Email class). The purpose
        # is to prevent bugtool from searching for TNs in the patch
        # itself.
        #
        # For the diff, there is one subtlelty:
        # Git commands calls strip on the output, which is usually
        # a good thing, but not in the case of the diff output.
        # Prevent this from happening by putting an artificial
        # character at the start of the format string, and then
        # by stripping it from the output.

        body = git.log(commit.rev, max_count="1") + '\n'
        if git_config('hooks.commit-url') is not None:
            url_info = {'rev': commit.rev, 'ref_name': self.ref_name}
            body = (git_config('hooks.commit-url') % url_info + '\n\n' + body)

        if git_config('hooks.disable-email-diff'):
            diff = None
        else:
            diff = git.show(commit.rev,
                            p=True,
                            M=True,
                            stat=True,
                            pretty="format:|")[1:]

        filer_cmd = git_config('hooks.file-commit-cmd')
        if filer_cmd is not None:
            filer_cmd = shlex.split(filer_cmd)

        email_bcc = git_config('hooks.filer-email')

        email = Email(self.email_info,
                      commit.email_to(self.ref_name),
                      email_bcc,
                      subject,
                      body,
                      commit.author,
                      self.ref_name,
                      commit.base_rev_for_display(),
                      commit.rev,
                      diff,
                      filer_cmd=filer_cmd)
        email.enqueue()
Exemple #8
0
    def get_standard_commit_email(self, commit):
        """See AbstractUpdate.get_standard_commit_email."""
        notes = GitNotes(commit.rev)

        # Get commit info for the annotated commit
        annotated_commit = commit_info_list("-1", notes.annotated_rev)[0]

        # Get a description of the annotated commit (a la "git show"),
        # except that we do not want the diff.
        #
        # Also, we have to handle the notes manually, as the commands
        # get the notes from the HEAD of the notes/commits branch,
        # whereas what we needs is the contents at the commit.rev.
        # This makes a difference when a single push updates the notes
        # of the same commit multiple times.
        annotated_rev_log = git.log(annotated_commit.rev,
                                    no_notes=True,
                                    max_count="1",
                                    _decode=True)
        notes_contents = (None if notes.contents is None else indent(
            notes.contents, " " * 4))

        # Get the list of references the annotated commit is contained in.
        annotated_commit_ref_names = git.for_each_ref(
            contains=annotated_commit.rev,
            format="%(refname)",
            _decode=True,
            _split_lines=True,
        )
        # Strip from that list all the references which are to be ignored
        # (typically, those are internal references).
        annotated_commit_ref_names = [
            ref_name for ref_name in annotated_commit_ref_names
            if search_config_option_list("hooks.ignore-refs", ref_name) is None
        ]

        subject_prefix = commit_email_subject_prefix(
            project_name=self.email_info.project_name,
            ref_names=annotated_commit_ref_names,
        )

        # Determine subject tag based on ref name:
        #   * remove "refs/notes" prefix
        #   * remove entire tag if remaining component is "commits"
        #     (case of the default refs/notes/commits ref)
        notes_ref = self.ref_name.split("/", 2)[2]
        if notes_ref == "commits":
            subject_tag = ""
        else:
            subject_tag = "(%s)" % notes_ref

        subject = f"[notes{subject_tag}]{subject_prefix} {annotated_commit.subject}"

        body_template = (DELETED_NOTES_COMMIT_EMAIL_BODY_TEMPLATE
                         if notes_contents is None else
                         UPDATED_NOTES_COMMIT_EMAIL_BODY_TEMPLATE)
        body = body_template % {
            "annotated_rev_log": annotated_rev_log,
            "notes_contents": notes_contents,
        }

        # Git commands calls strip on the output, which is usually
        # a good thing, but not in the case of the diff output.
        # Prevent this from happening by putting an artificial
        # character at the start of the format string, and then
        # by stripping it from the output.
        diff = git.show(commit.rev, pretty="format:|", p=True,
                        _decode=True)[1:]

        refs_containing_annotated_commit_section = (
            REFS_CONTAINING_ANNOTATED_COMMIT_TEMPLATE.format(
                annotated_commit_references="\n".join([
                    f"    {ref_name}"
                    for ref_name in annotated_commit_ref_names
                ])))

        email_bcc = git_config("hooks.filer-email")

        return Email(
            self.email_info,
            annotated_commit.email_to(self.ref_name),
            email_bcc,
            subject,
            body,
            commit.full_author_email,
            self.ref_name,
            commit.base_rev_for_display(),
            commit.rev,
            # Place the refs_containing_annotated_commit_section inside
            # the "Diff:" section to avoid having that section trigger
            # some unexpected filing.
            refs_containing_annotated_commit_section + diff,
        )
Exemple #9
0
    def get_standard_commit_email(self, commit):
        """Return an Email object for the given commit.

        Here, "standard" means that the Email returned corresponds
        to the Email the git-hooks sends by default, before any
        possible project-specific customization is applied.

        Before sending this email, users of this method are expected
        to apply those customizations as needed.

        PARAMETERS
            commit: A CommitInfo object.
        """
        subject_prefix = commit_email_subject_prefix(
            self.email_info.project_name,
            self.ref_name,
        )

        subject = f"{subject_prefix} {commit.subject[:SUBJECT_MAX_SUBJECT_CHARS]}"

        # Generate the body of the email in two pieces:
        #   1. The commit description without the patch;
        #   2. The diff stat and patch.
        # This allows us to insert our little "Diff:" marker that
        # bugtool detects when parsing the email for filing (this
        # part is now performed by the Email class). The purpose
        # is to prevent bugtool from searching for TNs in the patch
        # itself.

        body = git.log(commit.rev, max_count="1", _decode=True) + "\n"
        if git_config("hooks.commit-url") is not None:
            url_info = {"rev": commit.rev, "ref_name": self.ref_name}
            body = git_config("hooks.commit-url") % url_info + "\n\n" + body

        if git_config("hooks.disable-email-diff"):
            diff = None
        else:
            diff = git.show(commit.rev, p=True, M=True, stat=True, pretty="format:")
            # Decode the diff line-by-line:
            #
            # It seems conceivable that the diff may cover multiple files,
            # and that the files may have different encodings, so we cannot
            # assume that the entire output follows the same encoding.
            diff = safe_decode_by_line(diff)

            # Add a small "---" separator line at the beginning of
            # the diff section we just computed. This mimicks what
            # "git show" would do if we hadn't provided an empty
            # "format:" string to the "--pretty" command-line option.
            diff = "---\n" + diff

        filer_cmd = git_config("hooks.file-commit-cmd")
        if filer_cmd is not None:
            filer_cmd = shlex.split(filer_cmd)

        email_bcc = git_config("hooks.filer-email")

        return Email(
            self.email_info,
            commit.email_to(self.ref_name),
            email_bcc,
            subject,
            body,
            commit.full_author_email,
            self.ref_name,
            commit.base_rev_for_display(),
            commit.rev,
            diff,
            filer_cmd=filer_cmd,
        )