Store draft PatchLineComments in Git notes

The draft comments for a user will be stored in their own unique ref
in the All-Users repository. The ref will look like
'refs/users/34/1234/comments-5678' where the user's accountId is 1234
and the change's changeId is 5678. Since these commits will live in a
different repository than the change at a different ref, I created two
new classes (ChangeDraftUpdate and DraftCommentNotes) to mimic the
workflow of ChangeNotes and ChangeUpdate.

The basic workflow is that when a draft comment is added, it will be
written to a note attached to the user's ref for the given change in
the All-Users repository. However, whenever a draft is published or
deleted, then it should be removed from that location and instead
written to the same place as the other published comments (in the
notes attached to the commits in the meta ref related to the given
change).

Additionally, I added a helper method to TestChanges to help construct
ChangeDraftUpdates for test. Finally, I added test coverage for
storing draft PatchLineComments in the notedb to ChangeNotesTest.

Change-Id: I178b039529937c2a65a0efed388ee6ca1043aaa7
This commit is contained in:
Yacob Yonas
2014-07-15 11:37:36 -07:00
parent 7ab4e80071
commit 1ef3b37c88
12 changed files with 947 additions and 52 deletions

View File

@@ -19,6 +19,7 @@ import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_PATCH_SET;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_STATUS;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_SUBMITTED_WITH;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.GERRIT_PLACEHOLDER_HOST;
import static com.google.gerrit.server.notedb.CommentsInNotesUtil.getCommentPsId;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Enums;
@@ -49,8 +50,11 @@ import com.google.gerrit.reviewdb.client.PatchSet.Id;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.PatchSetApproval.LabelId;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.AllUsersNameProvider;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.util.LabelVote;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -134,15 +138,17 @@ public class ChangeNotes extends AbstractChangeNotes<ChangeNotes> {
@Singleton
public static class Factory {
private final GitRepositoryManager repoManager;
private final AllUsersNameProvider allUsersProvider;
@VisibleForTesting
@Inject
public Factory(GitRepositoryManager repoManager) {
public Factory(GitRepositoryManager repoManager, AllUsersNameProvider allUsersProvider) {
this.repoManager = repoManager;
this.allUsersProvider = allUsersProvider;
}
public ChangeNotes create(Change change) {
return new ChangeNotes(repoManager, change);
return new ChangeNotes(repoManager, allUsersProvider, change);
}
}
@@ -492,9 +498,15 @@ public class ChangeNotes extends AbstractChangeNotes<ChangeNotes> {
private ImmutableListMultimap<PatchSet.Id, PatchLineComment> commentsForPS;
NoteMap noteMap;
private final AllUsersName allUsers;
private DraftCommentNotes draftCommentNotes;
@Inject
@VisibleForTesting
public ChangeNotes(GitRepositoryManager repoManager, Change change) {
public ChangeNotes(GitRepositoryManager repoManager,
AllUsersNameProvider allUsersProvider, Change change) {
super(repoManager, change);
this.allUsers = allUsersProvider.get();
}
public ImmutableListMultimap<PatchSet.Id, PatchSetApproval> getApprovals() {
@@ -530,6 +542,55 @@ public class ChangeNotes extends AbstractChangeNotes<ChangeNotes> {
return commentsForPS;
}
public Table<PatchSet.Id, String, PatchLineComment> getDraftBaseComments(
Account.Id author) throws OrmException {
loadDraftComments(author);
return draftCommentNotes.getDraftBaseComments();
}
public Table<PatchSet.Id, String, PatchLineComment> getDraftPsComments(
Account.Id author) throws OrmException {
loadDraftComments(author);
return draftCommentNotes.getDraftPsComments();
}
/**
* If draft comments have already been loaded for this author, then they will
* not be reloaded. However, this method will load the comments if no draft
* comments have been loaded or if the caller would like the drafts for
* another author.
*/
private void loadDraftComments(Account.Id author)
throws OrmException {
if (draftCommentNotes == null ||
!author.equals(draftCommentNotes.getAuthor())) {
draftCommentNotes = new DraftCommentNotes(repoManager, allUsers,
getChange(), author);
draftCommentNotes.load();
}
}
public boolean containsComment(PatchLineComment c) throws OrmException {
if (containsCommentPublished(c)) {
return true;
}
loadDraftComments(c.getAuthor());
return draftCommentNotes.containsComment(c);
}
public boolean containsCommentPublished(PatchLineComment c) {
PatchSet.Id psId = getCommentPsId(c);
List<PatchLineComment> list = (c.getSide() == (short) 0)
? getBaseComments().get(psId)
: getPatchSetComments().get(psId);
for (PatchLineComment l : list) {
if (c.getKey().equals(l.getKey())) {
return true;
}
}
return false;
}
/** @return the NoteMap */
NoteMap getNoteMap() {
return noteMap;