use of com.google.gerrit.server.notedb.ChangeNotes in project gerrit by GerritCodeReview.
the class PublishCommentUtil method publish.
public void publish(ChangeContext ctx, ChangeUpdate changeUpdate, Collection<HumanComment> draftComments, @Nullable String tag) {
ChangeNotes notes = ctx.getNotes();
checkArgument(notes != null);
if (draftComments.isEmpty()) {
return;
}
Map<PatchSet.Id, PatchSet> patchSets = psUtil.getAsMap(notes, draftComments.stream().map(d -> psId(notes, d)).collect(toSet()));
Set<HumanComment> commentsToPublish = new HashSet<>();
for (HumanComment draftComment : draftComments) {
PatchSet.Id psIdOfDraftComment = psId(notes, draftComment);
PatchSet ps = patchSets.get(psIdOfDraftComment);
if (ps == null) {
// This can happen if changes with the same numeric ID exist:
// - change 12345 has 3 patch sets in repo X
// - another change 12345 has 7 patch sets in repo Y
// - the user saves a draft comment on patch set 6 of the change in repo Y
// - this draft comment gets stored in:
// AllUsers -> refs/draft-comments/45/12345/<account-id>
// - when posting a review with draft handling PUBLISH_ALL_REVISIONS on the change in
// repo X, the draft comments are loaded from
// AllUsers -> refs/draft-comments/45/12345/<account-id>, including the draft
// comment that was saved for patch set 6 of the change in repo Y
// - patch set 6 does not exist for the change in repo x, hence we get null for the patch
// set here
// Instead of failing hard (and returning an Internal Server Error) to the caller,
// just ignore that comment.
// Gerrit ensures that numeric change IDs are unique, but you can get duplicates if
// change refs of one repo are copied/pushed to another repo on the same host (this
// should never be done, but we know it happens).
logger.atWarning().log("Ignoring draft comment %s on non existing patch set %s (repo = %s)", draftComment, psIdOfDraftComment, notes.getProjectName());
continue;
}
draftComment.writtenOn = Timestamp.from(ctx.getWhen());
draftComment.tag = tag;
// Draft may have been created by a different real user; copy the current real user. (Only
// applies to X-Gerrit-RunAs, since modifying drafts via on_behalf_of is not allowed.)
ctx.getUser().updateRealAccountId(draftComment::setRealAuthor);
commentsUtil.setCommentCommitId(draftComment, notes.getChange(), ps);
commentsToPublish.add(draftComment);
}
commentsUtil.putHumanComments(changeUpdate, HumanComment.Status.PUBLISHED, commentsToPublish);
}
use of com.google.gerrit.server.notedb.ChangeNotes in project gerrit by GerritCodeReview.
the class GroupCollector method create.
/**
* Returns a new {@link GroupCollector} instance.
*
* @see GroupCollector for what this class does.
*/
public static GroupCollector create(ReceivePackRefCache receivePackRefCache, PatchSetUtil psUtil, ChangeNotes.Factory notesFactory, Project.NameKey project) {
return new GroupCollector(receivePackRefCache, psId -> {
// TODO(dborowitz): Reuse open repository from caller.
ChangeNotes notes = notesFactory.createChecked(project, psId.changeId());
PatchSet ps = psUtil.get(notes, psId);
return ps != null ? ps.groups() : null;
});
}
use of com.google.gerrit.server.notedb.ChangeNotes in project gerrit by GerritCodeReview.
the class CommentPorter method port.
private ImmutableList<HumanComment> port(ChangeNotes notes, PatchSet targetPatchset, List<HumanComment> comments) {
Map<Integer, ImmutableList<HumanComment>> commentsPerPatchset = comments.stream().collect(groupingBy(comment -> comment.key.patchSetId, toImmutableList()));
ImmutableList.Builder<HumanComment> portedComments = ImmutableList.builderWithExpectedSize(comments.size());
for (Integer originalPatchsetId : commentsPerPatchset.keySet()) {
ImmutableList<HumanComment> patchsetComments = commentsPerPatchset.get(originalPatchsetId);
PatchSet originalPatchset = notes.getPatchSets().get(PatchSet.id(notes.getChangeId(), originalPatchsetId));
if (originalPatchset != null) {
portedComments.addAll(portSamePatchset(notes.getProjectName(), notes.getChange(), originalPatchset, targetPatchset, patchsetComments));
} else {
logger.atWarning().log("Some comments which should be ported refer to the non-existent patchset %s of" + " change %d. Omitting %d affected comments.", originalPatchsetId, notes.getChangeId().get(), patchsetComments.size());
}
}
return portedComments.build();
}
use of com.google.gerrit.server.notedb.ChangeNotes in project gerrit by GerritCodeReview.
the class ChangesCollection method parse.
@Override
public ChangeResource parse(TopLevelResource root, IdString id) throws RestApiException, PermissionBackendException, IOException {
List<ChangeNotes> notes = changeFinder.find(id.encoded(), 2);
if (notes.isEmpty()) {
throw new ResourceNotFoundException(id);
} else if (notes.size() != 1) {
throw new ResourceNotFoundException("Multiple changes found for " + id);
}
ChangeNotes change = notes.get(0);
if (!canRead(change)) {
throw new ResourceNotFoundException(id);
}
checkProjectStatePermitsRead(change.getProjectName());
return changeResourceFactory.create(change, user.get());
}
use of com.google.gerrit.server.notedb.ChangeNotes in project gerrit by GerritCodeReview.
the class DeleteComment method apply.
@Override
public Response<CommentInfo> apply(HumanCommentResource rsrc, DeleteCommentInput input) throws RestApiException, IOException, ConfigInvalidException, PermissionBackendException, UpdateException {
CurrentUser user = userProvider.get();
permissionBackend.user(user).check(GlobalPermission.ADMINISTRATE_SERVER);
if (input == null) {
input = new DeleteCommentInput();
}
String newMessage = getCommentNewMessage(user.asIdentifiedUser().getName(), input.reason);
DeleteCommentOp deleteCommentOp = new DeleteCommentOp(rsrc, newMessage);
try (BatchUpdate batchUpdate = updateFactory.create(rsrc.getRevisionResource().getProject(), user, TimeUtil.now())) {
batchUpdate.addOp(rsrc.getRevisionResource().getChange().getId(), deleteCommentOp).execute();
}
ChangeNotes updatedNotes = notesFactory.createChecked(rsrc.getRevisionResource().getProject(), rsrc.getRevisionResource().getChangeResource().getId());
List<HumanComment> changeComments = commentsUtil.publishedHumanCommentsByChange(updatedNotes);
Optional<HumanComment> updatedComment = changeComments.stream().filter(c -> c.key.equals(rsrc.getComment().key)).findFirst();
if (!updatedComment.isPresent()) {
// This should not happen as this endpoint should not remove the whole comment.
throw new ResourceNotFoundException("comment not found: " + rsrc.getComment().key);
}
return Response.ok(commentJson.get().newHumanCommentFormatter().format(updatedComment.get()));
}
Aggregations