Migrate GerritClientComments to direct GerritApi
Note that test configuration has to be cleaned a bit so that Mockito was
not complayning about not used mocks...
Bug: Issue 336577745
Change-Id: I06aeadfcd265c2794fda80d5bbbd115305266c00
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientComments.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientComments.java
index 9729c4a..1a3d968 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientComments.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientComments.java
@@ -1,22 +1,24 @@
package com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit;
+import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.server.events.CommentAddedEvent;
-import com.google.gson.reflect.TypeToken;
+import com.google.gerrit.server.util.ManualRequestContext;
import com.googlesource.gerrit.plugins.chatgpt.config.Configuration;
-import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.UriResourceLocator;
import com.googlesource.gerrit.plugins.chatgpt.mode.common.client.messages.ClientMessage;
+import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritCodeRange;
import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.api.gerrit.GerritComment;
import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.ChangeSetData;
import com.googlesource.gerrit.plugins.chatgpt.mode.common.model.data.CommentData;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
-import java.lang.reflect.Type;
-import java.net.URI;
+import static java.util.stream.Collectors.toList;
+
import java.util.*;
-import static com.googlesource.gerrit.plugins.chatgpt.utils.GsonUtils.getGson;
import static com.googlesource.gerrit.plugins.chatgpt.utils.TimeUtils.getTimeStamp;
+import static com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClientDetail.toAuthor;
+import static com.googlesource.gerrit.plugins.chatgpt.mode.common.client.api.gerrit.GerritClientDetail.toDateString;
import static com.googlesource.gerrit.plugins.chatgpt.settings.Settings.GERRIT_PATCH_SET_FILENAME;
@Slf4j
@@ -69,41 +71,64 @@
}
private List<GerritComment> retrieveComments(GerritChange change) throws Exception {
- URI uri = URI.create(config.getGerritAuthBaseUrl()
- + UriResourceLocator.gerritGetAllPatchSetCommentsUri(change.getFullChangeId()));
- String responseBody = forwardGetRequest(uri);
- Type mapEntryType = new TypeToken<Map<String, List<GerritComment>>>(){}.getType();
- Map<String, List<GerritComment>> lastCommentMap = getGson().fromJson(responseBody, mapEntryType);
+ try (ManualRequestContext requestContext = config.openRequestContext()) {
+ Map<String, List<CommentInfo>> comments =
+ config
+ .getGerritApi()
+ .changes()
+ .id(
+ change.getProjectName(),
+ change.getBranchNameKey().shortName(),
+ change.getChangeKey().get())
+ .commentsRequest()
+ .get();
- String latestChangeMessageId = null;
- HashMap<String, List<GerritComment>> latestComments = new HashMap<>();
- for (Map.Entry<String, List<GerritComment>> entry : lastCommentMap.entrySet()) {
- String filename = entry.getKey();
- log.info("Commented filename: {}", filename);
+ // note that list of Map.Entry was used in order to keep the original response order
+ List<Map.Entry<String, List<GerritComment>>> lastCommentEntries =
+ comments.entrySet().stream()
+ .map(
+ entry ->
+ Map.entry(
+ entry.getKey(),
+ entry.getValue().stream()
+ .map(GerritClientComments::toComment)
+ .collect(toList())))
+ .collect(toList());
- List<GerritComment> commentsArray = entry.getValue();
+ String latestChangeMessageId = null;
+ HashMap<String, List<GerritComment>> latestComments = new HashMap<>();
+ for (Map.Entry<String, List<GerritComment>> entry : lastCommentEntries) {
+ String filename = entry.getKey();
+ log.info("Commented filename: {}", filename);
- for (GerritComment commentObject : commentsArray) {
- commentObject.setFilename(filename);
- String commentId = commentObject.getId();
- String changeMessageId = commentObject.getChangeMessageId();
- String commentAuthorUsername = commentObject.getAuthor().getUsername();
- log.debug("Change Message Id: {} - Author: {}", latestChangeMessageId, commentAuthorUsername);
- long updatedTimeStamp = getTimeStamp(commentObject.getUpdated());
- if (commentAuthorUsername.equals(authorUsername) &&
- updatedTimeStamp >= change.getEventTimeStamp() - MAX_SECS_GAP_BETWEEN_EVENT_AND_COMMENT) {
- log.debug("Found comment with updatedTimeStamp : {}", updatedTimeStamp);
- latestChangeMessageId = changeMessageId;
- }
- latestComments.computeIfAbsent(changeMessageId, k -> new ArrayList<>()).add(commentObject);
- commentMap.put(commentId, commentObject);
- if (filename.equals(GERRIT_PATCH_SET_FILENAME)) {
- patchSetCommentMap.put(changeMessageId, commentObject);
+ List<GerritComment> commentsArray = entry.getValue();
+
+ for (GerritComment commentObject : commentsArray) {
+ commentObject.setFilename(filename);
+ String commentId = commentObject.getId();
+ String changeMessageId = commentObject.getChangeMessageId();
+ String commentAuthorUsername = commentObject.getAuthor().getUsername();
+ log.debug(
+ "Change Message Id: {} - Author: {}", latestChangeMessageId, commentAuthorUsername);
+ long updatedTimeStamp = getTimeStamp(commentObject.getUpdated());
+ if (commentAuthorUsername.equals(authorUsername)
+ && updatedTimeStamp
+ >= change.getEventTimeStamp() - MAX_SECS_GAP_BETWEEN_EVENT_AND_COMMENT) {
+ log.debug("Found comment with updatedTimeStamp : {}", updatedTimeStamp);
+ latestChangeMessageId = changeMessageId;
+ }
+ latestComments
+ .computeIfAbsent(changeMessageId, k -> new ArrayList<>())
+ .add(commentObject);
+ commentMap.put(commentId, commentObject);
+ if (filename.equals(GERRIT_PATCH_SET_FILENAME)) {
+ patchSetCommentMap.put(changeMessageId, commentObject);
+ }
}
}
- }
- return latestComments.getOrDefault(latestChangeMessageId, null);
+ return latestComments.getOrDefault(latestChangeMessageId, null);
+ }
}
private void addLastComments(GerritChange change) {
@@ -131,4 +156,30 @@
}
}
+ private static GerritComment toComment(CommentInfo comment) {
+ GerritComment gerritComment = new GerritComment();
+ gerritComment.setAuthor(toAuthor(comment.author));
+ gerritComment.setChangeMessageId(comment.changeMessageId);
+ gerritComment.setUnresolved(comment.unresolved);
+ gerritComment.setPatchSet(comment.patchSet);
+ gerritComment.setId(comment.id);
+ gerritComment.setTag(comment.tag);
+ gerritComment.setLine(comment.line);
+ Optional.ofNullable(comment.range)
+ .ifPresent(
+ range ->
+ gerritComment.setRange(
+ GerritCodeRange.builder()
+ .startLine(range.startLine)
+ .endLine(range.endLine)
+ .startCharacter(range.startCharacter)
+ .endCharacter(range.endCharacter)
+ .build()));
+ gerritComment.setInReplyTo(comment.inReplyTo);
+ Optional.ofNullable(comment.updated)
+ .ifPresent(updated -> gerritComment.setUpdated(toDateString(updated)));
+ gerritComment.setMessage(comment.message);
+ gerritComment.setCommitId(comment.commitId);
+ return gerritComment;
+ }
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientDetail.java b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientDetail.java
index 4f6350e..7bda0e3 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientDetail.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/chatgpt/mode/common/client/api/gerrit/GerritClientDetail.java
@@ -145,7 +145,7 @@
return comment;
}
- private static GerritComment.Author toAuthor(AccountInfo authorInfo ) {
+ static GerritComment.Author toAuthor(AccountInfo authorInfo ) {
GerritComment.Author author = new GerritComment.Author();
author.setAccountId(authorInfo._accountId);
author.setName(authorInfo.name);
@@ -158,7 +158,7 @@
/**
* Date format copied from <b>com.google.gerrit.json.SqlTimestampDeserializer</b>
*/
- private static String toDateString(Timestamp input) {
+ static String toDateString(Timestamp input) {
return DATE_FORMAT.format(input) + "000000";
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatelessTest.java b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatelessTest.java
index c4fb24f..a7797ca 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatelessTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewStatelessTest.java
@@ -52,6 +52,7 @@
.thenReturn(GPT_STREAM_OUTPUT);
when(globalConfig.getBoolean(Mockito.eq("gptReviewCommitMessages"), Mockito.anyBoolean()))
.thenReturn(true);
+ when(globalConfig.getString("gerritUserName")).thenReturn(GERRIT_GPT_USERNAME);
super.initConfig();
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewTestBase.java b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewTestBase.java
index c969231..5c557ef 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewTestBase.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/ChatGptReviewTestBase.java
@@ -15,11 +15,13 @@
import com.google.gerrit.extensions.api.accounts.Accounts;
import com.google.gerrit.extensions.api.accounts.Accounts.QueryRequest;
import com.google.gerrit.extensions.api.changes.ChangeApi;
+import com.google.gerrit.extensions.api.changes.ChangeApi.CommentsRequest;
import com.google.gerrit.extensions.api.changes.Changes;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.changes.RevisionApi;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.json.OutputFormat;
@@ -72,6 +74,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Optional;
+import java.util.Map;
import java.util.function.Consumer;
import static com.google.gerrit.extensions.client.ChangeKind.REWORK;
@@ -122,6 +125,8 @@
protected ChangeApi changeApiMock;
@Mock
protected RevisionApi revisionApiMock;
+ @Mock
+ protected CommentsRequest commentsRequestMock;
protected PluginConfig globalConfig;
protected PluginConfig projectConfig;
@@ -153,9 +158,6 @@
};
// Mock the Global Config values not provided by Default
- when(globalConfig.getString("gerritAuthBaseUrl")).thenReturn(GERRIT_AUTH_BASE_URL);
- when(globalConfig.getString("gerritUserName")).thenReturn(GERRIT_USER_USERNAME);
- when(globalConfig.getString("gerritPassword")).thenReturn(GERRIT_USER_PASSWORD);
when(globalConfig.getString("gptToken")).thenReturn(GPT_TOKEN);
// Mock the Global Config values to the Defaults passed as second arguments of the `get*` methods.
@@ -175,9 +177,6 @@
protected void initConfig() {
config = new Configuration(context, gerritApi, globalConfig, projectConfig, "gpt@email.com", Account.id(1000000));
-
- // Mock the config instance values
- when(config.getGerritUserName()).thenReturn(GERRIT_GPT_USERNAME);
}
protected void setupMockRequests() throws RestApiException {
@@ -215,6 +214,7 @@
.withStatus(HTTP_OK)
.withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
.withBodyFile("gerritPatchSetComments.json")));
+ mockGerritChangeCommentsApiCall();
// Mock the behavior of the postReview request
WireMock.stubFor(WireMock.post(gerritSetReviewUri(fullChangeId))
@@ -252,6 +252,15 @@
when(changeApiMock.get()).thenReturn(changeInfo);
}
+ private void mockGerritChangeCommentsApiCall() throws RestApiException {
+ Map<String, List<CommentInfo>> comments =
+ readTestFileToType(
+ "__files/gerritPatchSetComments.json",
+ new TypeLiteral<Map<String, List<CommentInfo>>>() {}.getType());
+ when(changeApiMock.commentsRequest()).thenReturn(commentsRequestMock);
+ when(commentsRequestMock.get()).thenReturn(comments);
+ }
+
private void mockGerritChangeApiRestEndpoint() throws RestApiException {
when(gerritApi.changes()).thenReturn(changesMock);
when(changesMock.id(PROJECT_NAME.get(), BRANCH_NAME.shortName(), CHANGE_ID.get())).thenReturn(changeApiMock);