use of com.google.gerrit.reviewdb.client.Comment in project gerrit by GerritCodeReview.
the class CommentsUtil method publish.
public void publish(ChangeContext ctx, PatchSet.Id psId, Collection<Comment> drafts, @Nullable String tag) throws OrmException {
ChangeNotes notes = ctx.getNotes();
checkArgument(notes != null);
if (drafts.isEmpty()) {
return;
}
Map<PatchSet.Id, PatchSet> patchSets = psUtil.getAsMap(ctx.getDb(), notes, drafts.stream().map(d -> psId(notes, d)).collect(toSet()));
for (Comment d : drafts) {
PatchSet ps = patchSets.get(psId(notes, d));
if (ps == null) {
throw new OrmException("patch set " + ps + " not found");
}
d.writtenOn = ctx.getWhen();
d.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(d::setRealAuthor);
setCommentRevId(d, patchListCache, notes.getChange(), ps);
}
putComments(ctx.getDb(), ctx.getUpdate(psId), PUBLISHED, drafts);
}
use of com.google.gerrit.reviewdb.client.Comment in project gerrit by GerritCodeReview.
the class CommentsUtil method newComment.
public Comment newComment(ChangeContext ctx, String path, PatchSet.Id psId, short side, String message, @Nullable Boolean unresolved, @Nullable String parentUuid) throws OrmException, UnprocessableEntityException {
if (unresolved == null) {
if (parentUuid == null) {
// Default to false if comment is not descended from another.
unresolved = false;
} else {
// Inherit unresolved value from inReplyTo comment if not specified.
Comment.Key key = new Comment.Key(parentUuid, path, psId.patchSetId);
Optional<Comment> parent = get(ctx.getDb(), ctx.getNotes(), key);
if (!parent.isPresent()) {
throw new UnprocessableEntityException("Invalid parentUuid supplied for comment");
}
unresolved = parent.get().unresolved;
}
}
Comment c = new Comment(new Comment.Key(ChangeUtil.messageUuid(), path, psId.get()), ctx.getUser().getAccountId(), ctx.getWhen(), side, message, serverId, unresolved);
c.parentUuid = parentUuid;
ctx.getUser().updateRealAccountId(c::setRealAuthor);
return c;
}
use of com.google.gerrit.reviewdb.client.Comment in project gerrit by GerritCodeReview.
the class DraftComments method parse.
@Override
public DraftCommentResource parse(RevisionResource rev, IdString id) throws ResourceNotFoundException, OrmException, AuthException {
checkIdentifiedUser();
String uuid = id.get();
for (Comment c : commentsUtil.draftByPatchSetAuthor(dbProvider.get(), rev.getPatchSet().getId(), rev.getAccountId(), rev.getNotes())) {
if (uuid.equals(c.key.uuid)) {
return new DraftCommentResource(rev, c);
}
}
throw new ResourceNotFoundException(id);
}
use of com.google.gerrit.reviewdb.client.Comment in project gerrit by GerritCodeReview.
the class ListChangeDrafts method apply.
@Override
public Map<String, List<CommentInfo>> apply(ChangeResource rsrc) throws AuthException, OrmException {
if (!rsrc.getControl().getUser().isIdentifiedUser()) {
throw new AuthException("Authentication required");
}
ChangeData cd = changeDataFactory.create(db.get(), rsrc.getControl());
List<Comment> drafts = commentsUtil.draftByChangeAuthor(db.get(), cd.notes(), rsrc.getControl().getUser().getAccountId());
return commentJson.get().setFillAccounts(false).setFillPatchSet(true).newCommentFormatter().format(drafts);
}
use of com.google.gerrit.reviewdb.client.Comment in project gerrit by GerritCodeReview.
the class HtmlParser method parse.
/**
* Parses comments from html email.
*
* @param email MailMessage as received from the email service.
* @param comments A specific set of comments as sent out in the original notification email.
* Comments are expected to be in the same order as they were sent out to in the email
* @param changeUrl Canonical change URL that points to the change on this Gerrit instance.
* Example: https://go-review.googlesource.com/#/c/91570
* @return List of MailComments parsed from the html part of the email.
*/
public static List<MailComment> parse(MailMessage email, Collection<Comment> comments, String changeUrl) {
// TODO(hiesel) Add support for Gmail Mobile
// TODO(hiesel) Add tests for other popular email clients
// This parser goes though all html elements in the email and checks for
// matching patterns. It keeps track of the last file and comments it
// encountered to know in which context a parsed comment belongs.
// It uses the href attributes of <a> tags to identify comments sent out by
// Gerrit as these are generally more reliable then the text captions.
List<MailComment> parsedComments = new ArrayList<>();
Document d = Jsoup.parse(email.htmlContent());
PeekingIterator<Comment> iter = Iterators.peekingIterator(comments.iterator());
String lastEncounteredFileName = null;
Comment lastEncounteredComment = null;
for (Element e : d.body().getAllElements()) {
String elementName = e.tagName();
boolean isInBlockQuote = e.parents().stream().filter(p -> p.tagName().equals("blockquote")).findAny().isPresent();
if (elementName.equals("a")) {
String href = e.attr("href");
// this <a> tag
if (!iter.hasNext()) {
continue;
}
Comment perspectiveComment = iter.peek();
if (href.equals(ParserUtil.filePath(changeUrl, perspectiveComment))) {
if (lastEncounteredFileName == null || !lastEncounteredFileName.equals(perspectiveComment.key.filename)) {
// Not a file-level comment, but users could have typed a comment
// right after this file annotation to create a new file-level
// comment. If this file has a file-level comment, we have already
// set lastEncounteredComment to that file-level comment when we
// encountered the file link and should not reset it now.
lastEncounteredFileName = perspectiveComment.key.filename;
lastEncounteredComment = null;
} else if (perspectiveComment.lineNbr == 0) {
// This was originally a file-level comment
lastEncounteredComment = perspectiveComment;
iter.next();
}
} else if (ParserUtil.isCommentUrl(href, changeUrl, perspectiveComment)) {
// This is a regular inline comment
lastEncounteredComment = perspectiveComment;
iter.next();
}
} else if (!isInBlockQuote && elementName.equals("div") && !e.className().startsWith("gmail")) {
// This is a comment typed by the user
// Replace non-breaking spaces and trim string
String content = e.ownText().replace(' ', ' ').trim();
if (!Strings.isNullOrEmpty(content)) {
if (lastEncounteredComment == null && lastEncounteredFileName == null) {
// Remove quotation line, email signature and
// "Sent from my xyz device"
content = ParserUtil.trimQuotation(content);
// TODO(hiesel) Add more sanitizer
if (!Strings.isNullOrEmpty(content)) {
parsedComments.add(new MailComment(content, null, null, MailComment.CommentType.CHANGE_MESSAGE));
}
} else if (lastEncounteredComment == null) {
parsedComments.add(new MailComment(content, lastEncounteredFileName, null, MailComment.CommentType.FILE_COMMENT));
} else {
parsedComments.add(new MailComment(content, null, lastEncounteredComment, MailComment.CommentType.INLINE_COMMENT));
}
}
}
}
return parsedComments;
}
Aggregations