Merge changes from topic "change-messages-rest-api"

* changes:
  Add REST endpoint to get one change message
  Add REST endpoint for listing change messages
This commit is contained in:
David Pursehouse 2018-05-08 01:11:55 +00:00 committed by Gerrit Code Review
commit a72fbf418e
15 changed files with 568 additions and 14 deletions

View File

@ -2403,6 +2403,87 @@ As response the change's hashtags are returned as a list of strings.
]
----
[[list-change-messages]]
=== List Change Messages
--
'GET /changes/link:#change-id[\{change-id\}]/messages'
--
Lists all the messages of a change including link:#detailed-accounts[detailed account information].
.Request
----
GET /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/messages
----
As response a list of link:#change-message-info[ChangeMessageInfo] entities is returned.
.Response
----
HTTP/1.1 200 OK
Content-Disposition: attachment
Content-Type: application/json; charset=UTF-8
)]}'
[
{
"id": "YH-egE",
"author": {
"_account_id": 1000096,
"name": "John Doe",
"email": "john.doe@example.com",
"username": "jdoe"
},
"date": "2013-03-23 21:34:02.419000000",
"message": "Patch Set 1:\n\nThis is the first message.",
"_revision_number": 1
},
{
"id": "WEEdhU",
"author": {
"_account_id": 1000097,
"name": "Jane Roe",
"email": "jane.roe@example.com",
"username": "jroe"
},
"date": "2013-03-23 21:36:52.332000000",
"message": "Patch Set 1:\n\nThis is the second message.\n\nWith a line break.",
"_revision_number": 1
}
]
----
[[get-change-message]]
=== Get Change Message
Retrieves a change message including link:#detailed-accounts[detailed account information].
--
'GET /changes/link:#change-id[\{change-id\}]/message/link:#change-message-id[\{change-message-id\}'
--
As response a link:#change-message-info[ChangeMessageInfo] entity is returned.
.Response
----
HTTP/1.1 200 OK
Content-Disposition: attachment
Content-Type: application/json; charset=UTF-8
)]}'
{
"id": "aaee04dcb46bafc8be24d8aa70b3b1beb7df5780",
"author": {
"_account_id": 1000096,
"name": "John Doe",
"email": "john.doe@example.com",
"username": "jdoe"
},
"date": "2013-03-23 21:34:02.419000000",
"message": "Change message removed by: Administrator; Reason: spam",
"_revision_number": 1
}
----
[[edit-endpoints]]
== Change Edit Endpoints
@ -5366,6 +5447,10 @@ If you need more time to migrate off of old change IDs, please see
link:config-gerrit.html#change.api.allowedIdentifier[change.api.allowedIdentifier]
for more information on how to enable the use of deprecated identifiers.
[[change-message-id]]
=== \{change-message-id\}
ID of a change message returned in a link:#change-message-info[ChangeMessageInfo].
[[comment-id]]
=== \{comment-id\}
UUID of a published comment.

View File

@ -19,6 +19,7 @@ import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.common.CommitMessageInput;
import com.google.gerrit.extensions.common.EditInfo;
@ -283,6 +284,25 @@ public interface ChangeApi {
/** Check if this change is a pure revert of claimedOriginal (SHA1 in 40 digit hex). */
PureRevertInfo pureRevert(String claimedOriginal) throws RestApiException;
/**
* Get all messages of a change with detailed account info.
*
* @return a list of messages sorted by their creation time.
* @throws RestApiException
*/
List<ChangeMessageInfo> messages() throws RestApiException;
/**
* Look up a change message of a change by its id.
*
* @param id the id of the change message. Note that in NoteDb, this id is the {@code ObjectId} of
* a commit on the change meta branch. In ReviewDb, it's a UUID generated randomly. That means
* a change message id could be different between NoteDb and ReviewDb.
* @return API for accessing a change message.
* @throws RestApiException if the id is invalid.
*/
ChangeMessageApi message(String id) throws RestApiException;
abstract class SuggestedReviewersRequest {
private String query;
private int limit;
@ -590,5 +610,15 @@ public interface ChangeApi {
public PureRevertInfo pureRevert(String claimedOriginal) throws RestApiException {
throw new NotImplementedException();
}
@Override
public List<ChangeMessageInfo> messages() throws RestApiException {
throw new NotImplementedException();
}
@Override
public ChangeMessageApi message(String id) throws RestApiException {
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,36 @@
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.extensions.api.changes;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.restapi.NotImplementedException;
import com.google.gerrit.extensions.restapi.RestApiException;
/** Interface for change message APIs. */
public interface ChangeMessageApi {
/** Gets one change message. */
ChangeMessageInfo get() throws RestApiException;
/**
* A default implementation which allows source compatibility when adding new methods to the
* interface.
*/
class NotImplemented implements ChangeMessageApi {
@Override
public ChangeMessageInfo get() throws RestApiException {
throw new NotImplementedException();
}
}
}

View File

@ -15,6 +15,7 @@
package com.google.gerrit.extensions.common;
import java.sql.Timestamp;
import java.util.Objects;
public class ChangeMessageInfo {
public String id;
@ -24,4 +25,24 @@ public class ChangeMessageInfo {
public Timestamp date;
public String message;
public Integer _revisionNumber;
@Override
public boolean equals(Object o) {
if (o instanceof ChangeMessageInfo) {
ChangeMessageInfo cmi = (ChangeMessageInfo) o;
return Objects.equals(id, cmi.id)
&& Objects.equals(tag, cmi.tag)
&& Objects.equals(author, cmi.author)
&& Objects.equals(realAuthor, cmi.realAuthor)
&& Objects.equals(date, cmi.date)
&& Objects.equals(message, cmi.message)
&& Objects.equals(_revisionNumber, cmi._revisionNumber);
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(id, tag, author, realAuthor, date, message, _revisionNumber);
}
}

View File

@ -19,10 +19,12 @@ import static com.google.common.base.Preconditions.checkState;
import com.google.common.annotations.VisibleForTesting;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.notedb.NotesMigration;
@ -141,4 +143,21 @@ public class ChangeMessagesUtil {
public static boolean isAutogenerated(@Nullable String tag) {
return tag != null && tag.startsWith(AUTOGENERATED_TAG_PREFIX);
}
public static ChangeMessageInfo createChangeMessageInfo(
ChangeMessage message, AccountLoader accountLoader) {
PatchSet.Id patchNum = message.getPatchSetId();
ChangeMessageInfo cmi = new ChangeMessageInfo();
cmi.id = message.getKey().get();
cmi.author = accountLoader.get(message.getAuthor());
cmi.date = message.getWrittenOn();
cmi.message = message.getMessage();
cmi.tag = message.getTag();
cmi._revisionNumber = patchNum != null ? patchNum.get() : null;
Account.Id realAuthor = message.getRealAuthor();
if (realAuthor != null) {
cmi.realAuthor = accountLoader.get(realAuthor);
}
return cmi;
}
}

View File

@ -23,6 +23,7 @@ import com.google.gerrit.extensions.api.changes.AddReviewerResult;
import com.google.gerrit.extensions.api.changes.AssigneeInput;
import com.google.gerrit.extensions.api.changes.ChangeApi;
import com.google.gerrit.extensions.api.changes.ChangeEditApi;
import com.google.gerrit.extensions.api.changes.ChangeMessageApi;
import com.google.gerrit.extensions.api.changes.Changes;
import com.google.gerrit.extensions.api.changes.FixInput;
import com.google.gerrit.extensions.api.changes.HashtagsInput;
@ -39,6 +40,7 @@ import com.google.gerrit.extensions.api.changes.TopicInput;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.common.CommitMessageInput;
import com.google.gerrit.extensions.common.EditInfo;
@ -53,11 +55,13 @@ import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.StarredChangesUtil;
import com.google.gerrit.server.StarredChangesUtil.IllegalLabelException;
import com.google.gerrit.server.change.ChangeJson;
import com.google.gerrit.server.change.ChangeMessageResource;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.PureRevert;
import com.google.gerrit.server.change.WorkInProgressOp;
import com.google.gerrit.server.restapi.change.Abandon;
import com.google.gerrit.server.restapi.change.ChangeIncludedIn;
import com.google.gerrit.server.restapi.change.ChangeMessages;
import com.google.gerrit.server.restapi.change.Check;
import com.google.gerrit.server.restapi.change.CreateMergePatchSet;
import com.google.gerrit.server.restapi.change.DeleteAssignee;
@ -111,6 +115,8 @@ class ChangeApiImpl implements ChangeApi {
private final Revisions revisions;
private final ReviewerApiImpl.Factory reviewerApi;
private final RevisionApiImpl.Factory revisionApi;
private final ChangeMessageApiImpl.Factory changeMessageApi;
private final ChangeMessages changeMessages;
private final SuggestChangeReviewers suggestReviewers;
private final ChangeResource change;
private final Abandon abandon;
@ -157,6 +163,8 @@ class ChangeApiImpl implements ChangeApi {
Revisions revisions,
ReviewerApiImpl.Factory reviewerApi,
RevisionApiImpl.Factory revisionApi,
ChangeMessageApiImpl.Factory changeMessageApi,
ChangeMessages changeMessages,
SuggestChangeReviewers suggestReviewers,
Abandon abandon,
Revert revert,
@ -201,6 +209,8 @@ class ChangeApiImpl implements ChangeApi {
this.revisions = revisions;
this.reviewerApi = reviewerApi;
this.revisionApi = revisionApi;
this.changeMessageApi = changeMessageApi;
this.changeMessages = changeMessages;
this.suggestReviewers = suggestReviewers;
this.abandon = abandon;
this.restore = restore;
@ -709,4 +719,23 @@ class ChangeApiImpl implements ChangeApi {
throw asRestApiException("Cannot compute pure revert", e);
}
}
@Override
public List<ChangeMessageInfo> messages() throws RestApiException {
try {
return changeMessages.list().apply(change);
} catch (Exception e) {
throw asRestApiException("Cannot list change messages", e);
}
}
@Override
public ChangeMessageApi message(String id) throws RestApiException {
try {
ChangeMessageResource resource = changeMessages.parse(change, IdString.fromDecoded(id));
return changeMessageApi.create(resource);
} catch (Exception e) {
throw asRestApiException("Cannot parse change message " + id, e);
}
}
}

View File

@ -0,0 +1,50 @@
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.server.api.changes;
import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
import com.google.gerrit.extensions.api.changes.ChangeMessageApi;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.change.ChangeMessageResource;
import com.google.gerrit.server.restapi.change.GetChangeMessage;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
class ChangeMessageApiImpl implements ChangeMessageApi {
interface Factory {
ChangeMessageApiImpl create(ChangeMessageResource changeMessageResource);
}
private final GetChangeMessage getChangeMessage;
private final ChangeMessageResource changeMessageResource;
@Inject
ChangeMessageApiImpl(
GetChangeMessage getChangeMessage, @Assisted ChangeMessageResource changeMessageResource) {
this.getChangeMessage = getChangeMessage;
this.changeMessageResource = changeMessageResource;
}
@Override
public ChangeMessageInfo get() throws RestApiException {
try {
return getChangeMessage.apply(changeMessageResource);
} catch (Exception e) {
throw asRestApiException("Cannot retrieve change message", e);
}
}
}

View File

@ -31,5 +31,6 @@ public class Module extends FactoryModule {
factory(ReviewerApiImpl.Factory.class);
factory(RevisionReviewerApiImpl.Factory.class);
factory(ChangeEditApiImpl.Factory.class);
factory(ChangeMessageApiImpl.Factory.class);
}
}

View File

@ -37,6 +37,7 @@ import static com.google.gerrit.extensions.client.ListChangesOption.SKIP_MERGEAB
import static com.google.gerrit.extensions.client.ListChangesOption.SUBMITTABLE;
import static com.google.gerrit.extensions.client.ListChangesOption.TRACKING_IDS;
import static com.google.gerrit.extensions.client.ListChangesOption.WEB_LINKS;
import static com.google.gerrit.server.ChangeMessagesUtil.createChangeMessageInfo;
import static com.google.gerrit.server.CommonConverters.toGitPerson;
import static java.util.stream.Collectors.toList;
@ -1189,19 +1190,7 @@ public class ChangeJson {
List<ChangeMessageInfo> result = Lists.newArrayListWithCapacity(messages.size());
for (ChangeMessage message : messages) {
PatchSet.Id patchNum = message.getPatchSetId();
ChangeMessageInfo cmi = new ChangeMessageInfo();
cmi.id = message.getKey().get();
cmi.author = accountLoader.get(message.getAuthor());
cmi.date = message.getWrittenOn();
cmi.message = message.getMessage();
cmi.tag = message.getTag();
cmi._revisionNumber = patchNum != null ? patchNum.get() : null;
Account.Id realAuthor = message.getRealAuthor();
if (realAuthor != null) {
cmi.realAuthor = accountLoader.get(realAuthor);
}
result.add(cmi);
result.add(createChangeMessageInfo(message, accountLoader));
}
return result;
}

View File

@ -0,0 +1,63 @@
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.server.change;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.restapi.RestResource;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.reviewdb.client.Change;
import com.google.inject.TypeLiteral;
/** A change message resource. */
public class ChangeMessageResource implements RestResource {
public static final TypeLiteral<RestView<ChangeMessageResource>> CHANGE_MESSAGE_KIND =
new TypeLiteral<RestView<ChangeMessageResource>>() {};
private final ChangeResource changeResource;
private final ChangeMessageInfo changeMessage;
private final int changeMessageIndex;
public ChangeMessageResource(
ChangeResource changeResource, ChangeMessageInfo changeMessage, int changeMessageIndex) {
this.changeResource = changeResource;
this.changeMessage = changeMessage;
this.changeMessageIndex = changeMessageIndex;
}
public ChangeResource getChangeResource() {
return changeResource;
}
public ChangeMessageInfo getChangeMessage() {
return changeMessage;
}
public Change.Id getChangeId() {
return changeResource.getId();
}
public String getChangeMessageId() {
return changeMessage.id;
}
/**
* Gets the index of the change message among all messages of the change sorted by creation time.
*
* @return the index of the change message.
*/
public int getChangeMessageIndex() {
return changeMessageIndex;
}
}

View File

@ -0,0 +1,73 @@
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.server.restapi.change;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.ChildCollection;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.server.change.ChangeMessageResource;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.List;
@Singleton
public class ChangeMessages implements ChildCollection<ChangeResource, ChangeMessageResource> {
private final DynamicMap<RestView<ChangeMessageResource>> views;
private final ListChangeMessages listChangeMessages;
@Inject
ChangeMessages(
DynamicMap<RestView<ChangeMessageResource>> views, ListChangeMessages listChangeMessages) {
this.views = views;
this.listChangeMessages = listChangeMessages;
}
@Override
public DynamicMap<RestView<ChangeMessageResource>> views() {
return views;
}
@Override
public ListChangeMessages list() {
return listChangeMessages;
}
@Override
public ChangeMessageResource parse(ChangeResource parent, IdString id)
throws OrmException, ResourceNotFoundException {
String uuid = id.get();
List<ChangeMessageInfo> changeMessages = listChangeMessages.apply(parent);
int index = -1;
for (int i = 0; i < changeMessages.size(); ++i) {
ChangeMessageInfo changeMessage = changeMessages.get(i);
if (changeMessage.id.equals(uuid)) {
index = i;
break;
}
}
if (index < 0) {
throw new ResourceNotFoundException(String.format("change message %s not found", uuid));
}
return new ChangeMessageResource(parent, changeMessages.get(index), index);
}
}

View File

@ -0,0 +1,29 @@
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.server.restapi.change;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.server.change.ChangeMessageResource;
import com.google.inject.Singleton;
/** Gets one change message. */
@Singleton
public class GetChangeMessage implements RestReadView<ChangeMessageResource> {
@Override
public ChangeMessageInfo apply(ChangeMessageResource resource) {
return resource.getChangeMessage();
}
}

View File

@ -0,0 +1,61 @@
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.server.restapi.change;
import static com.google.gerrit.server.ChangeMessagesUtil.createChangeMessageInfo;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.util.List;
import java.util.stream.Collectors;
@Singleton
public class ListChangeMessages implements RestReadView<ChangeResource> {
private final Provider<ReviewDb> dbProvider;
private final ChangeMessagesUtil changeMessagesUtil;
private final AccountLoader accountLoader;
@Inject
public ListChangeMessages(
Provider<ReviewDb> dbProvider,
ChangeMessagesUtil changeMessagesUtil,
AccountLoader.Factory accountLoaderFactory) {
this.dbProvider = dbProvider;
this.changeMessagesUtil = changeMessagesUtil;
this.accountLoader = accountLoaderFactory.create(true);
}
@Override
public List<ChangeMessageInfo> apply(ChangeResource resource) throws OrmException {
List<ChangeMessage> messages =
changeMessagesUtil.byChange(dbProvider.get(), resource.getNotes());
List<ChangeMessageInfo> messageInfos =
messages
.stream()
.map(m -> createChangeMessageInfo(m, accountLoader))
.collect(Collectors.toList());
accountLoader.fill();
return messageInfos;
}
}

View File

@ -15,6 +15,7 @@
package com.google.gerrit.server.restapi.change;
import static com.google.gerrit.server.change.ChangeEditResource.CHANGE_EDIT_KIND;
import static com.google.gerrit.server.change.ChangeMessageResource.CHANGE_MESSAGE_KIND;
import static com.google.gerrit.server.change.ChangeResource.CHANGE_KIND;
import static com.google.gerrit.server.change.CommentResource.COMMENT_KIND;
import static com.google.gerrit.server.change.DraftCommentResource.DRAFT_COMMENT_KIND;
@ -65,6 +66,7 @@ public class Module extends RestApiModule {
DynamicMap.mapOf(binder(), REVISION_KIND);
DynamicMap.mapOf(binder(), CHANGE_EDIT_KIND);
DynamicMap.mapOf(binder(), VOTE_KIND);
DynamicMap.mapOf(binder(), CHANGE_MESSAGE_KIND);
get(CHANGE_KIND).to(GetChange.class);
post(CHANGE_KIND, "merge").to(CreateMergePatchSet.class);
@ -174,6 +176,9 @@ public class Module extends RestApiModule {
get(CHANGE_EDIT_KIND, "meta").to(ChangeEdits.GetMeta.class);
post(COMMIT_KIND, "cherrypick").to(CherryPickCommit.class);
child(CHANGE_KIND, "messages").to(ChangeMessages.class);
get(CHANGE_MESSAGE_KIND).to(GetChangeMessage.class);
factory(AccountLoader.Factory.class);
factory(ChangeEdits.Create.Factory.class);
factory(ChangeEdits.DeleteFile.Factory.class);

View File

@ -15,16 +15,22 @@
package com.google.gerrit.acceptance.rest.change;
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.PushOneCommit.FILE_NAME;
import static com.google.gerrit.extensions.client.ListChangesOption.MESSAGES;
import static java.util.concurrent.TimeUnit.SECONDS;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.testing.ConfigSuite;
import com.google.gerrit.testing.TestTimeUtil;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -95,7 +101,64 @@ public class ChangeMessagesIT extends AbstractDaemonTest {
assertThat(actual.tag).isEqualTo(tag);
}
private void assertMessage(String expected, String actual) {
@Test
public void listChangeMessages() throws Exception {
int changeNum = createOneChangeWithMultipleChangeMessagesInHistory();
List<ChangeMessageInfo> messages1 = gApi.changes().id(changeNum).messages();
List<ChangeMessageInfo> messages2 =
new ArrayList<>(gApi.changes().id(changeNum).get().messages);
assertThat(messages1).containsExactlyElementsIn(messages2).inOrder();
}
@Test
public void getOneChangeMessage() throws Exception {
int changeNum = createOneChangeWithMultipleChangeMessagesInHistory();
List<ChangeMessageInfo> messages = new ArrayList<>(gApi.changes().id(changeNum).get().messages);
for (ChangeMessageInfo messageInfo : messages) {
String id = messageInfo.id;
assertThat(gApi.changes().id(changeNum).message(id).get()).isEqualTo(messageInfo);
}
}
private int createOneChangeWithMultipleChangeMessagesInHistory() throws Exception {
setApiUser(user);
// Commit 1: create a change.
PushOneCommit.Result result = createChange();
String changeId = result.getChangeId();
// Commit 2: post a review with message "message 1".
setApiUser(admin);
addOneReview(changeId, "message 1");
// Commit 3: amend a new patch set.
setApiUser(user);
amendChange(changeId);
// Commit 4: post a review with message "message 2".
addOneReview(changeId, "message 2");
// Commit 5: amend a new patch set.
amendChange(changeId);
// Commit 6: approve the change.
setApiUser(admin);
gApi.changes().id(changeId).current().review(ReviewInput.approve());
// commit 7: submit the change.
gApi.changes().id(changeId).current().submit();
return result.getChange().getId().get();
}
private void addOneReview(String changeId, String changeMessage) throws Exception {
ReviewInput.CommentInput c = new ReviewInput.CommentInput();
c.line = 1;
c.message = "comment 1";
c.path = FILE_NAME;
ReviewInput reviewInput = new ReviewInput().label("Code-Review", 1);
reviewInput.comments = ImmutableMap.of(c.path, Lists.newArrayList(c));
reviewInput.message = changeMessage;
gApi.changes().id(changeId).current().review(reviewInput);
}
private static void assertMessage(String expected, String actual) {
assertThat(actual).isEqualTo("Patch Set 1:\n\n" + expected);
}