Notify users mentioned in commit footer on draft publish

If a user is mentioned in a footer of a commit message (e.g. by a
'Signed-off-by') then this user is notified about this change/patchset.
This is important because the mentioned user may want to check that he
is correctly referenced.

If a draft change/patchset is uploaded the users mentioned in the
footers cannot be notified because the draft is not visible to them.
But they should be notified when the draft is published since the
change/patchset is now visible to them.

Change-Id: Id28a7b0aa47d2de9dc97f2f3a743300ff7f4c559
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
This commit is contained in:
Edwin Kempin
2013-01-04 15:04:50 +01:00
committed by Gerrit Code Review
parent 013229c9a4
commit be46e51a20

View File

@@ -15,15 +15,24 @@
package com.google.gerrit.server.changedetail;
import static com.google.gerrit.server.mail.MailUtil.getRecipientsFromFooters;
import com.google.gerrit.common.ChangeHooks;
import com.google.gerrit.common.data.ReviewResult;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetInfo;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.mail.CreateChangeSender;
import com.google.gerrit.server.mail.MailUtil.MailRecipients;
import com.google.gerrit.server.mail.ReplacePatchSetSender;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
import com.google.gerrit.server.project.ChangeControl;
@@ -33,9 +42,16 @@ import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.FooterLine;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.Callable;
public class PublishDraft implements Callable<ReviewResult> {
@@ -49,29 +65,39 @@ public class PublishDraft implements Callable<ReviewResult> {
private final ChangeControl.Factory changeControlFactory;
private final ReviewDb db;
private final ChangeHooks hooks;
private final GitRepositoryManager repoManager;
private final PatchSetInfoFactory patchSetInfoFactory;
private final AccountResolver accountResolver;
private final CreateChangeSender.Factory createChangeSenderFactory;
private final ReplacePatchSetSender.Factory replacePatchSetFactory;
private final PatchSet.Id patchSetId;
@Inject
PublishDraft(final ChangeControl.Factory changeControlFactory,
final ReviewDb db, final ChangeHooks hooks,
final GitRepositoryManager repoManager,
final PatchSetInfoFactory patchSetInfoFactory,
final ApprovalsUtil approvalsUtil,
final AccountResolver accountResolver,
final CreateChangeSender.Factory createChangeSenderFactory,
final ReplacePatchSetSender.Factory replacePatchSetFactory,
@Assisted final PatchSet.Id patchSetId) {
this.changeControlFactory = changeControlFactory;
this.db = db;
this.hooks = hooks;
this.repoManager = repoManager;
this.patchSetInfoFactory = patchSetInfoFactory;
this.accountResolver = accountResolver;
this.createChangeSenderFactory = createChangeSenderFactory;
this.replacePatchSetFactory = replacePatchSetFactory;
this.patchSetId = patchSetId;
}
@Override
public ReviewResult call() throws NoSuchChangeException, OrmException,
PatchSetInfoNotAvailableException {
IOException, PatchSetInfoNotAvailableException {
final ReviewResult result = new ReviewResult();
final Change.Id changeId = patchSetId.getParentKey();
@@ -115,27 +141,65 @@ public class PublishDraft implements Callable<ReviewResult> {
if (!updatedPatchSet.isDraft() || updatedChange.getStatus() == Change.Status.NEW) {
hooks.doDraftPublishedHook(updatedChange, updatedPatchSet, db);
if (control.getChange().getStatus() == Change.Status.DRAFT) {
notifyWatchers((IdentifiedUser) control.getCurrentUser(),
updatedChange, updatedPatchSet);
}
sendNotifications(control.getChange().getStatus() == Change.Status.DRAFT,
(IdentifiedUser) control.getCurrentUser(), updatedChange, updatedPatchSet);
}
}
return result;
}
private void notifyWatchers(final IdentifiedUser currentUser,
final Change updatedChange, final PatchSet updatedPatchSet)
throws PatchSetInfoNotAvailableException {
final PatchSetInfo info = patchSetInfoFactory.get(updatedChange, updatedPatchSet);
private void sendNotifications(final boolean newChange,
final IdentifiedUser currentUser, final Change updatedChange,
final PatchSet updatedPatchSet) throws OrmException, IOException,
PatchSetInfoNotAvailableException {
final Repository git = repoManager.openRepository(updatedChange.getProject());
try {
CreateChangeSender cm = createChangeSenderFactory.create(updatedChange);
cm.setFrom(currentUser.getAccountId());
cm.setPatchSet(updatedPatchSet, info);
cm.send();
} catch (Exception e) {
log.error("Cannot send email for new change " + updatedChange.getId(), e);
final RevWalk revWalk = new RevWalk(git);
final RevCommit commit;
try {
commit = revWalk.parseCommit(ObjectId.fromString(updatedPatchSet.getRevision().get()));
} finally {
revWalk.release();
}
final PatchSetInfo info = patchSetInfoFactory.get(commit, updatedPatchSet.getId());
final List<FooterLine> footerLines = commit.getFooterLines();
final Account.Id me = currentUser.getAccountId();
final MailRecipients recipients =
getRecipientsFromFooters(accountResolver, updatedPatchSet, footerLines);
recipients.remove(me);
if (newChange) {
try {
CreateChangeSender cm = createChangeSenderFactory.create(updatedChange);
cm.setFrom(me);
cm.setPatchSet(updatedPatchSet, info);
cm.addReviewers(recipients.getReviewers());
cm.addExtraCC(recipients.getCcOnly());
cm.send();
} catch (Exception e) {
log.error("Cannot send email for new change " + updatedChange.getId(), e);
}
} else {
final ChangeMessage msg =
new ChangeMessage(new ChangeMessage.Key(updatedChange.getId(),
ChangeUtil.messageUUID(db)), me,
updatedPatchSet.getCreatedOn(), updatedPatchSet.getId());
msg.setMessage("Uploaded patch set " + updatedPatchSet.getPatchSetId() + ".");
try {
ReplacePatchSetSender cm = replacePatchSetFactory.create(updatedChange);
cm.setFrom(me);
cm.setPatchSet(updatedPatchSet, info);
cm.setChangeMessage(msg);
cm.addReviewers(recipients.getReviewers());
cm.addExtraCC(recipients.getCcOnly());
cm.send();
} catch (Exception e) {
log.error("Cannot send email for new patch set " + updatedPatchSet.getId(), e);
}
}
} finally {
git.close();
}
}
}