When gerrit sends emails from itself for a change (as opposed to
on behalf of someone), those messages should also go into the change history.
This commit is contained in:
@@ -34,6 +34,8 @@ def _encode_safely(s):
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
def _to_email_string(obj):
|
def _to_email_string(obj):
|
||||||
|
if not obj:
|
||||||
|
return None
|
||||||
if isinstance(obj, str):
|
if isinstance(obj, str):
|
||||||
return obj
|
return obj
|
||||||
elif isinstance(obj, unicode):
|
elif isinstance(obj, unicode):
|
||||||
@@ -50,12 +52,18 @@ def _to_email_string(obj):
|
|||||||
result = str(email)
|
result = str(email)
|
||||||
return _encode_safely(result)
|
return _encode_safely(result)
|
||||||
|
|
||||||
|
def _make_to_strings(to):
|
||||||
|
return [x for x in [_to_email_string(e) for e in to] if x]
|
||||||
|
|
||||||
|
|
||||||
def send(sender, to, subject, template, template_args):
|
def send(sender, to, subject, template, template_args):
|
||||||
"""Sends an email based on a template.
|
"""Sends an email based on a template.
|
||||||
|
|
||||||
All email address parameters can be: strings, unicode, db.Email users.User
|
All email address parameters can be: strings, unicode, db.Email users.User
|
||||||
or models.Account objects.
|
or models.Account objects.
|
||||||
|
|
||||||
|
Returns a Message object, suitable for keeping in the db.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
sender: The From address. Null if it should be sent from the role acct.
|
sender: The From address. Null if it should be sent from the role acct.
|
||||||
to: An email address or a list of email address to be in the To field.
|
to: An email address or a list of email address to be in the To field.
|
||||||
@@ -63,16 +71,16 @@ def send(sender, to, subject, template, template_args):
|
|||||||
template: The name of the template file to use from the mail dir.
|
template: The name of the template file to use from the mail dir.
|
||||||
template_args: A map of args to be pasaed to the template
|
template_args: A map of args to be pasaed to the template
|
||||||
"""
|
"""
|
||||||
if not sender:
|
sender_string = _to_email_string(sender)
|
||||||
sender_string = get_default_sender()
|
if not sender_string:
|
||||||
if not sender_string:
|
return 'no from address'
|
||||||
logging.warn('not sending email because there is no from address')
|
to_strings = _make_to_strings(to)
|
||||||
return 'not sending email because there is no from address'
|
if not to_strings:
|
||||||
else:
|
return 'no to addresses'
|
||||||
sender_string = _to_email_string(sender)
|
|
||||||
to_string = [_to_email_string(e) for e in to]
|
|
||||||
body = django.template.loader.render_to_string(template, template_args)
|
body = django.template.loader.render_to_string(template, template_args)
|
||||||
mail.send_mail(sender=sender_string, to=to_string, subject=subject, body=body)
|
mail.send_mail(sender=sender_string, to=to_strings, subject=subject,
|
||||||
|
body=body)
|
||||||
|
|
||||||
|
|
||||||
def make_change_subject(change):
|
def make_change_subject(change):
|
||||||
subject = "(%s) %s" % (change.dest_project.name, change.subject)
|
subject = "(%s) %s" % (change.dest_project.name, change.subject)
|
||||||
@@ -80,14 +88,49 @@ def make_change_subject(change):
|
|||||||
subject = 'Re: ' + subject
|
subject = 'Re: ' + subject
|
||||||
return subject
|
return subject
|
||||||
|
|
||||||
def send_change_message(request, change, template, template_args):
|
def send_change_message(request, change, template, template_args,
|
||||||
|
sender, send_email=True, email_template=None):
|
||||||
|
# sender
|
||||||
|
if not sender:
|
||||||
|
sender = get_default_sender()
|
||||||
|
sender_string = _to_email_string(sender)
|
||||||
|
|
||||||
|
# to
|
||||||
to_users = set([change.owner] + change.reviewers + change.cc)
|
to_users = set([change.owner] + change.reviewers + change.cc)
|
||||||
|
if sender in to_users:
|
||||||
|
to_users.remove(sender)
|
||||||
|
to_strings = _make_to_strings(to_users)
|
||||||
|
to_emails = [db.Email(s) for s in to_strings]
|
||||||
|
|
||||||
|
# subject
|
||||||
subject = make_change_subject(change)
|
subject = make_change_subject(change)
|
||||||
args = {
|
|
||||||
'url': library.change_url(change)
|
# body
|
||||||
}
|
uri = library.change_url(change)
|
||||||
if template_args:
|
if not email_template:
|
||||||
args.update(template_args)
|
email_template = template
|
||||||
email.send(request.user, to_users, subject, template, args)
|
body = django.template.loader.render_to_string(email_template, template_args)
|
||||||
|
|
||||||
|
# don't send emails without all of these fields
|
||||||
|
if not sender_string or not to_strings or not subject or not body:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# send the email
|
||||||
|
if send_email:
|
||||||
|
message_body = "%s\n--\n%s\n" % (body, uri)
|
||||||
|
mail.send_mail(sender=sender_string, to=to_strings, subject=subject,
|
||||||
|
body=message_body)
|
||||||
|
|
||||||
|
# make and return the email
|
||||||
|
if email_template != template:
|
||||||
|
body = django.template.loader.render_to_string(
|
||||||
|
template, template_args)
|
||||||
|
msg = models.Message(change=change,
|
||||||
|
subject=subject,
|
||||||
|
sender=sender_string,
|
||||||
|
recipients=to_emails,
|
||||||
|
text=db.Text(body),
|
||||||
|
parent=change)
|
||||||
|
return msg
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,22 +29,27 @@ from codereview import email
|
|||||||
|
|
||||||
def _send_clean_merge_email(http_request, change):
|
def _send_clean_merge_email(http_request, change):
|
||||||
if not change.emailed_clean_merge:
|
if not change.emailed_clean_merge:
|
||||||
email.send_change_message(http_request, change,
|
msg = email.send_change_message(http_request, change,
|
||||||
"mails/clean_merge.txt", None)
|
"mails/clean_merge.txt", None, None)
|
||||||
change.emailed_clean_merge = True
|
change.emailed_clean_merge = True
|
||||||
|
return msg
|
||||||
|
return None
|
||||||
|
|
||||||
def _send_missing_dependency_merge_email(http_request, change):
|
def _send_missing_dependency_merge_email(http_request, change):
|
||||||
if not change.emailed_clean_merge:
|
if not change.emailed_clean_merge:
|
||||||
email.send_change_message(http_request, change,
|
msg = email.send_change_message(http_request, change,
|
||||||
"mails/missing_dependency.txt", None)
|
"mails/missing_dependency.txt", None, None)
|
||||||
change.emailed_missing_dependency = True
|
change.emailed_missing_dependency = True
|
||||||
|
return msg
|
||||||
|
return None
|
||||||
|
|
||||||
def _send_path_conflict_email(http_request, change):
|
def _send_path_conflict_email(http_request, change):
|
||||||
if not change.emailed_clean_merge:
|
if not change.emailed_clean_merge:
|
||||||
email.send_change_message(http_request, change,
|
msg = email.send_change_message(http_request, change,
|
||||||
"mails/path_conflict.txt", None)
|
"mails/path_conflict.txt", None, None)
|
||||||
change.emailed_path_conflict = True
|
change.emailed_path_conflict = True
|
||||||
|
return msg
|
||||||
|
return None
|
||||||
|
|
||||||
class InvalidBranchStatusError(Exception):
|
class InvalidBranchStatusError(Exception):
|
||||||
"""The branch cannot be updated in this way at this time."""
|
"""The branch cannot be updated in this way at this time."""
|
||||||
@@ -115,22 +120,30 @@ class MergeServiceImp(MergeService, InternalAPI):
|
|||||||
change.put()
|
change.put()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if db.run_in_transaction(chg_trans, ps.change.key()):
|
if db.run_in_transaction(chg_trans, ps.change.key()):
|
||||||
if sc == MergeResultItem.CLEAN_MERGE:
|
if sc == MergeResultItem.CLEAN_MERGE:
|
||||||
_send_clean_merge_email(self.http_request, ps.change)
|
msg = _send_clean_merge_email(self.http_request, ps.change)
|
||||||
ps.change.put()
|
ps.change.put()
|
||||||
|
if msg:
|
||||||
|
msg.put()
|
||||||
|
|
||||||
elif sc == MergeResultItem.ALREADY_MERGED:
|
elif sc == MergeResultItem.ALREADY_MERGED:
|
||||||
success.append(ps)
|
success.append(ps)
|
||||||
|
|
||||||
elif sc == MergeResultItem.MISSING_DEPENDENCY:
|
elif sc == MergeResultItem.MISSING_DEPENDENCY:
|
||||||
_send_missing_dependency_merge_email(self.http_request, ps.change)
|
msg = _send_missing_dependency_merge_email(self.http_request,
|
||||||
|
ps.change)
|
||||||
ps.change.put()
|
ps.change.put()
|
||||||
|
if msg:
|
||||||
|
msg.put()
|
||||||
defer.append(ps)
|
defer.append(ps)
|
||||||
|
|
||||||
elif sc == MergeResultItem.PATH_CONFLICT:
|
elif sc == MergeResultItem.PATH_CONFLICT:
|
||||||
_send_path_conflict_email(self.http_request, ps.change)
|
msg = _send_path_conflict_email(self.http_request, ps.change)
|
||||||
ps.change.put()
|
ps.change.put()
|
||||||
|
if msg:
|
||||||
|
msg.put()
|
||||||
fail.append(ps)
|
fail.append(ps)
|
||||||
else:
|
else:
|
||||||
fail.append(ps)
|
fail.append(ps)
|
||||||
|
|||||||
@@ -1294,20 +1294,7 @@ def _get_draft_details(request, comments):
|
|||||||
def _make_comment_message(request, change, lgtm, verified, message,
|
def _make_comment_message(request, change, lgtm, verified, message,
|
||||||
comments=None, send_mail=False):
|
comments=None, send_mail=False):
|
||||||
"""Helper to create a Message instance and optionally send an email."""
|
"""Helper to create a Message instance and optionally send an email."""
|
||||||
# Decide who should receive mail
|
|
||||||
my_email = db.Email(request.user.email())
|
|
||||||
to = [db.Email(change.owner.email())] + change.reviewers
|
|
||||||
cc = change.cc[:]
|
|
||||||
reply_to = to + cc
|
|
||||||
if my_email in to and len(to) > 1: # send_mail() wants a non-empty to list
|
|
||||||
to.remove(my_email)
|
|
||||||
if my_email in cc:
|
|
||||||
cc.remove(my_email)
|
|
||||||
subject = email.make_change_subject(change)
|
|
||||||
if comments:
|
|
||||||
details = _get_draft_details(request, comments)
|
|
||||||
else:
|
|
||||||
details = ''
|
|
||||||
prefix = ''
|
prefix = ''
|
||||||
if lgtm:
|
if lgtm:
|
||||||
prefix = prefix + [y for (x,y) in models.LGTM_CHOICES
|
prefix = prefix + [y for (x,y) in models.LGTM_CHOICES
|
||||||
@@ -1316,26 +1303,24 @@ def _make_comment_message(request, change, lgtm, verified, message,
|
|||||||
prefix = prefix + 'Verified.\n'
|
prefix = prefix + 'Verified.\n'
|
||||||
if prefix:
|
if prefix:
|
||||||
prefix = prefix + '\n'
|
prefix = prefix + '\n'
|
||||||
|
|
||||||
message = message.replace('\r\n', '\n')
|
message = message.replace('\r\n', '\n')
|
||||||
message = prefix + message
|
message = prefix + message
|
||||||
text = ((message.strip() + '\n\n' + details.strip())).strip()
|
|
||||||
msg = models.Message(change=change,
|
|
||||||
subject=subject,
|
|
||||||
sender=my_email,
|
|
||||||
recipients=reply_to,
|
|
||||||
text=db.Text(text),
|
|
||||||
parent=change)
|
|
||||||
|
|
||||||
if send_mail:
|
if comments:
|
||||||
to_users = set([change.owner] + change.reviewers + cc)
|
details = _get_draft_details(request, comments)
|
||||||
template_args = {
|
else:
|
||||||
'message': message,
|
details = ''
|
||||||
'details': details,
|
|
||||||
}
|
|
||||||
email.send_change_message(request, change,
|
|
||||||
'mails/comment.txt', template_args)
|
|
||||||
|
|
||||||
return msg
|
template_args = {
|
||||||
|
'message': message,
|
||||||
|
'details': details,
|
||||||
|
}
|
||||||
|
|
||||||
|
return email.send_change_message(
|
||||||
|
request, change,
|
||||||
|
'mails/comment.txt', template_args, request.user,
|
||||||
|
send_mail, 'mails/comment-email.txt')
|
||||||
|
|
||||||
|
|
||||||
@xsrf_required
|
@xsrf_required
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ Hi.
|
|||||||
|
|
||||||
Your change has been successfully merged into the git repository.
|
Your change has been successfully merged into the git repository.
|
||||||
|
|
||||||
For more details, see {%autoescape off%}{{url}}{%endautoescape%}
|
|
||||||
|
|
||||||
-Your friendly git merger
|
-Your friendly git merger
|
||||||
|
|
||||||
{%endautoescape%}
|
{%endautoescape%}
|
||||||
|
|||||||
4
webapp/templates/mails/comment-email.txt
Normal file
4
webapp/templates/mails/comment-email.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{%autoescape off%}{%if message%}{{message|wordwrap:"72"}}
|
||||||
|
|
||||||
|
{%endif%}{%if details%}{{details|wordwrap:"72"}}
|
||||||
|
{%endif%}{%endautoescape%}
|
||||||
@@ -1,7 +1,2 @@
|
|||||||
{%autoescape off%}{%if message%}{{message|wordwrap:"72"}}
|
{%autoescape off%}{%if message%}{{message|wordwrap:"72"}}
|
||||||
|
|
||||||
{%endif%}{%if details%}{{details|wordwrap:"72"}}
|
|
||||||
{%endif%}{%endautoescape%}
|
{%endif%}{%endautoescape%}
|
||||||
--
|
|
||||||
To respond, visit {%autoescape off%}{{url}}{%endautoescape%}
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,9 @@
|
|||||||
Hi.
|
Hi.
|
||||||
|
|
||||||
Your change could not be merged because of a missing dependency. As
|
Your change could not be merged because of a missing dependency. As
|
||||||
soon as change XXX is submitted, your change will be submitted
|
soon as its dependencies are submitted, your change will be submitted
|
||||||
automatically.
|
automatically.
|
||||||
|
|
||||||
Your change: {%autoescape off%}{{url}}{%endautoescape%}
|
|
||||||
The missing change: {%autoescape off%}{{url}}{%endautoescape%}
|
|
||||||
|
|
||||||
-Your friendly git merger
|
-Your friendly git merger
|
||||||
|
|
||||||
{%endautoescape%}
|
{%endautoescape%}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
{%autoescape off%}
|
{%autoescape off%}
|
||||||
Hi.
|
Hi.
|
||||||
|
|
||||||
Your change has not been successfully merged into the git repository.
|
Your change has not been successfully merged into the git repository
|
||||||
|
because of a path conflict.
|
||||||
You need to resolve the following files before it can be submitted:
|
|
||||||
|
|
||||||
-Your friendly git merger
|
-Your friendly git merger
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user