~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/canonical/codehosting/scanner/email.py

  • Committer: Abel Deuring
  • Date: 2009-03-24 12:43:49 UTC
  • mfrom: (8053 devel)
  • mto: This revision was merged to the branch mainline in revision 8328.
  • Revision ID: abel.deuring@canonical.com-20090324124349-xllu9kbw5ib27kno
RF merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2009 Canonical Ltd.  All rights reserved.
 
2
 
 
3
"""Email code for the branch scanner."""
 
4
 
 
5
__metaclass__ = type
 
6
__all__ = [
 
7
    'BranchMailer',
 
8
    ]
 
9
 
 
10
from zope.component import getUtility
 
11
 
 
12
from canonical.config import config
 
13
from canonical.launchpad.interfaces import BranchSubscriptionNotificationLevel
 
14
from canonical.launchpad.interfaces.branchjob import IRevisionMailJobSource
 
15
 
 
16
 
 
17
class BranchMailer:
 
18
    """Handles mail notifications for changes to the code in a branch."""
 
19
 
 
20
    def __init__(self, trans_manager, db_branch):
 
21
        self.trans_manager = trans_manager
 
22
        self.db_branch = db_branch
 
23
        self.pending_emails = []
 
24
        self.subscribers_want_notification = False
 
25
        self.initial_scan = None
 
26
        self.email_from = config.canonical.noreply_from_address
 
27
 
 
28
    def initializeEmailQueue(self, initial_scan):
 
29
        """Create an email queue and determine whether to create diffs.
 
30
 
 
31
        In order to avoid sending emails when no one is interested in seeing
 
32
        them, we check all the branch subscriptions first, and decide here
 
33
        whether or not to generate the revision diffs as the branch is
 
34
        scanned.
 
35
 
 
36
        See XXX comment in `sendRevisionNotificationEmails` for the reason
 
37
        behind the queue itself.
 
38
        """
 
39
        self.pending_emails = []
 
40
        self.subscribers_want_notification = False
 
41
 
 
42
        diff_levels = (BranchSubscriptionNotificationLevel.DIFFSONLY,
 
43
                       BranchSubscriptionNotificationLevel.FULL)
 
44
 
 
45
        subscriptions = self.db_branch.getSubscriptionsByLevel(diff_levels)
 
46
        for subscription in subscriptions:
 
47
            self.subscribers_want_notification = True
 
48
 
 
49
        # If db_history is empty, then this is the initial scan of the
 
50
        # branch.  We only want to send one email for the initial scan
 
51
        # of a branch, not one for each revision.
 
52
        self.initial_scan = initial_scan
 
53
 
 
54
    def generateEmailForRemovedRevisions(self, removed_history):
 
55
        """Notify subscribers of removed revisions.
 
56
 
 
57
        When the history is shortened, and email is sent that says this. This
 
58
        will never happen for a newly scanned branch, so not checking that
 
59
        here.
 
60
        """
 
61
        if not self.subscribers_want_notification:
 
62
            return
 
63
        number_removed = len(removed_history)
 
64
        if number_removed > 0:
 
65
            if number_removed == 1:
 
66
                contents = '1 revision was removed from the branch.'
 
67
            else:
 
68
                contents = ('%d revisions were removed from the branch.'
 
69
                            % number_removed)
 
70
            # No diff is associated with the removed email.
 
71
            job = getUtility(IRevisionMailJobSource).create(
 
72
                self.db_branch, revno='removed', from_address=self.email_from,
 
73
                body=contents, perform_diff=False, subject=None)
 
74
            self.pending_emails.append(job)
 
75
 
 
76
    def sendRevisionNotificationEmails(self, bzr_history):
 
77
        """Send out the pending emails.
 
78
 
 
79
        If this is the first scan of a branch, then we send out a simple
 
80
        notification email saying that the branch has been scanned.
 
81
        """
 
82
        # XXX: thumper 2007-03-28 bug=29744:
 
83
        # The whole reason that this method exists is due to
 
84
        # emails being sent immediately in a zopeless environment.
 
85
        # When bug #29744 is fixed, this method will no longer be
 
86
        # necessary, and the emails should be sent at the source
 
87
        # instead of appending them to the pending_emails.
 
88
        # This method is enclosed in a transaction so emails will
 
89
        # continue to be sent out when the bug is closed without
 
90
        # immediately having to fix this method.
 
91
        # Now that these changes have been committed, send the pending emails.
 
92
        if not self.subscribers_want_notification:
 
93
            return
 
94
        self.trans_manager.begin()
 
95
 
 
96
        if self.initial_scan:
 
97
            assert len(self.pending_emails) == 0, (
 
98
                'Unexpected pending emails on new branch.')
 
99
            revision_count = len(bzr_history)
 
100
            if revision_count == 1:
 
101
                revisions = '1 revision'
 
102
            else:
 
103
                revisions = '%d revisions' % revision_count
 
104
            message = ('First scan of the branch detected %s'
 
105
                       ' in the revision history of the branch.' %
 
106
                       revisions)
 
107
 
 
108
            job = getUtility(IRevisionMailJobSource).create(
 
109
                self.db_branch, 'initial', self.email_from, message, False,
 
110
                None)
 
111
        self.trans_manager.commit()