1
# Copyright 2009 Canonical Ltd. All rights reserved.
3
"""Email code for the branch scanner."""
10
from zope.component import getUtility
12
from canonical.config import config
13
from canonical.launchpad.interfaces import BranchSubscriptionNotificationLevel
14
from canonical.launchpad.interfaces.branchjob import IRevisionMailJobSource
18
"""Handles mail notifications for changes to the code in a branch."""
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
28
def initializeEmailQueue(self, initial_scan):
29
"""Create an email queue and determine whether to create diffs.
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
36
See XXX comment in `sendRevisionNotificationEmails` for the reason
37
behind the queue itself.
39
self.pending_emails = []
40
self.subscribers_want_notification = False
42
diff_levels = (BranchSubscriptionNotificationLevel.DIFFSONLY,
43
BranchSubscriptionNotificationLevel.FULL)
45
subscriptions = self.db_branch.getSubscriptionsByLevel(diff_levels)
46
for subscription in subscriptions:
47
self.subscribers_want_notification = True
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
54
def generateEmailForRemovedRevisions(self, removed_history):
55
"""Notify subscribers of removed revisions.
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
61
if not self.subscribers_want_notification:
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.'
68
contents = ('%d revisions were removed from the branch.'
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)
76
def sendRevisionNotificationEmails(self, bzr_history):
77
"""Send out the pending emails.
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.
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:
94
self.trans_manager.begin()
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'
103
revisions = '%d revisions' % revision_count
104
message = ('First scan of the branch detected %s'
105
' in the revision history of the branch.' %
108
job = getUtility(IRevisionMailJobSource).create(
109
self.db_branch, 'initial', self.email_from, message, False,
111
self.trans_manager.commit()