Search in sources :

Example 31 with Comment

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;
}
Also used : Comment(com.google.gerrit.reviewdb.client.Comment) Element(org.jsoup.nodes.Element) ArrayList(java.util.ArrayList) Document(org.jsoup.nodes.Document)

Example 32 with Comment

use of com.google.gerrit.reviewdb.client.Comment in project gerrit by GerritCodeReview.

the class ChangeData method draftRefs.

public Map<Account.Id, Ref> draftRefs() throws OrmException {
    if (draftsByUser == null) {
        if (!lazyLoad) {
            return Collections.emptyMap();
        }
        Change c = change();
        if (c == null) {
            return Collections.emptyMap();
        }
        draftsByUser = new HashMap<>();
        if (notesMigration.readChanges()) {
            for (Ref ref : commentsUtil.getDraftRefs(notes.getChangeId())) {
                Account.Id account = Account.Id.fromRefSuffix(ref.getName());
                if (account != null && // this point.
                !notes().getDraftComments(account, ref).isEmpty()) {
                    draftsByUser.put(account, ref);
                }
            }
        } else {
            for (Comment sc : commentsUtil.draftByChange(db, notes())) {
                draftsByUser.put(sc.author.getId(), null);
            }
        }
    }
    return draftsByUser;
}
Also used : Account(com.google.gerrit.reviewdb.client.Account) Comment(com.google.gerrit.reviewdb.client.Comment) RobotComment(com.google.gerrit.reviewdb.client.RobotComment) StarRef(com.google.gerrit.server.StarredChangesUtil.StarRef) Ref(org.eclipse.jgit.lib.Ref) Change(com.google.gerrit.reviewdb.client.Change)

Example 33 with Comment

use of com.google.gerrit.reviewdb.client.Comment in project gerrit by GerritCodeReview.

the class DeleteDraftPatchSetIT method deleteDraftPS1.

@Test
public void deleteDraftPS1() throws Exception {
    String changeId = createDraftChangeWith2PS();
    ReviewInput rin = new ReviewInput();
    rin.message = "Change message";
    CommentInput cin = new CommentInput();
    cin.line = 1;
    cin.patchSet = 1;
    cin.path = PushOneCommit.FILE_NAME;
    cin.side = Side.REVISION;
    cin.message = "Inline comment";
    rin.comments = new HashMap<>();
    rin.comments.put(cin.path, ImmutableList.of(cin));
    gApi.changes().id(changeId).revision(1).review(rin);
    ChangeData cd = getChange(changeId);
    PatchSet.Id delPsId = new PatchSet.Id(cd.getId(), 1);
    PatchSet ps = cd.patchSet(delPsId);
    deletePatchSet(changeId, ps);
    cd = getChange(changeId);
    assertThat(cd.patchSets()).hasSize(1);
    assertThat(Iterables.getOnlyElement(cd.patchSets()).getId().get()).isEqualTo(2);
    // Other entities based on deleted patch sets are also deleted.
    for (ChangeMessage m : cd.messages()) {
        assertThat(m.getPatchSetId()).named(m.toString()).isNotEqualTo(delPsId);
    }
    for (Comment c : cd.publishedComments()) {
        assertThat(c.key.patchSetId).named(c.toString()).isNotEqualTo(delPsId.get());
    }
}
Also used : Comment(com.google.gerrit.reviewdb.client.Comment) CommentInput(com.google.gerrit.extensions.api.changes.ReviewInput.CommentInput) ChangeMessage(com.google.gerrit.reviewdb.client.ChangeMessage) PatchSet(com.google.gerrit.reviewdb.client.PatchSet) ReviewInput(com.google.gerrit.extensions.api.changes.ReviewInput) ChangeData(com.google.gerrit.server.query.change.ChangeData) Test(org.junit.Test) AbstractDaemonTest(com.google.gerrit.acceptance.AbstractDaemonTest)

Example 34 with Comment

use of com.google.gerrit.reviewdb.client.Comment in project gerrit by GerritCodeReview.

the class DeleteDraftPatchSetIT method deleteDraftPS2.

@Test
public void deleteDraftPS2() throws Exception {
    String changeId = createDraftChangeWith2PS();
    ReviewInput rin = new ReviewInput();
    rin.message = "Change message";
    CommentInput cin = new CommentInput();
    cin.line = 1;
    cin.patchSet = 1;
    cin.path = PushOneCommit.FILE_NAME;
    cin.side = Side.REVISION;
    cin.message = "Inline comment";
    rin.comments = new HashMap<>();
    rin.comments.put(cin.path, ImmutableList.of(cin));
    gApi.changes().id(changeId).revision(1).review(rin);
    ChangeData cd = getChange(changeId);
    PatchSet.Id delPsId = new PatchSet.Id(cd.getId(), 2);
    PatchSet ps = cd.patchSet(delPsId);
    deletePatchSet(changeId, ps);
    cd = getChange(changeId);
    assertThat(cd.patchSets()).hasSize(1);
    assertThat(Iterables.getOnlyElement(cd.patchSets()).getId().get()).isEqualTo(1);
    // Other entities based on deleted patch sets are also deleted.
    for (ChangeMessage m : cd.messages()) {
        assertThat(m.getPatchSetId()).named(m.toString()).isNotEqualTo(delPsId);
    }
    for (Comment c : cd.publishedComments()) {
        assertThat(c.key.patchSetId).named(c.toString()).isNotEqualTo(delPsId.get());
    }
}
Also used : Comment(com.google.gerrit.reviewdb.client.Comment) CommentInput(com.google.gerrit.extensions.api.changes.ReviewInput.CommentInput) ChangeMessage(com.google.gerrit.reviewdb.client.ChangeMessage) PatchSet(com.google.gerrit.reviewdb.client.PatchSet) ReviewInput(com.google.gerrit.extensions.api.changes.ReviewInput) ChangeData(com.google.gerrit.server.query.change.ChangeData) Test(org.junit.Test) AbstractDaemonTest(com.google.gerrit.acceptance.AbstractDaemonTest)

Example 35 with Comment

use of com.google.gerrit.reviewdb.client.Comment in project gerrit by GerritCodeReview.

the class CommentDetail method index.

private Map<Integer, List<Comment>> index(List<Comment> in) {
    HashMap<Integer, List<Comment>> r = new HashMap<>();
    for (Comment p : in) {
        List<Comment> l = r.get(p.lineNbr);
        if (l == null) {
            l = new ArrayList<>();
            r.put(p.lineNbr, l);
        }
        l.add(p);
    }
    return r;
}
Also used : Comment(com.google.gerrit.reviewdb.client.Comment) HashMap(java.util.HashMap) List(java.util.List) ArrayList(java.util.ArrayList)

Aggregations

Comment (com.google.gerrit.reviewdb.client.Comment)73 PatchSet (com.google.gerrit.reviewdb.client.PatchSet)38 Change (com.google.gerrit.reviewdb.client.Change)35 Test (org.junit.Test)34 CommentRange (com.google.gerrit.reviewdb.client.CommentRange)29 Timestamp (java.sql.Timestamp)29 RevId (com.google.gerrit.reviewdb.client.RevId)27 ObjectId (org.eclipse.jgit.lib.ObjectId)14 ArrayList (java.util.ArrayList)12 RobotComment (com.google.gerrit.reviewdb.client.RobotComment)11 Account (com.google.gerrit.reviewdb.client.Account)9 PatchLineComment (com.google.gerrit.reviewdb.client.PatchLineComment)8 ChangeNotesRevWalk (com.google.gerrit.server.notedb.ChangeNotesCommit.ChangeNotesRevWalk)7 Map (java.util.Map)6 Note (org.eclipse.jgit.notes.Note)6 NoteMap (org.eclipse.jgit.notes.NoteMap)6 RevWalk (org.eclipse.jgit.revwalk.RevWalk)6 ChangeData (com.google.gerrit.server.query.change.ChangeData)5 ChangeMessage (com.google.gerrit.reviewdb.client.ChangeMessage)4 ChangeNotes (com.google.gerrit.server.notedb.ChangeNotes)4