diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt index c2dc26482e..8cde19e8a4 100644 --- a/Documentation/rest-api-changes.txt +++ b/Documentation/rest-api-changes.txt @@ -2453,6 +2453,38 @@ As response a list of link:#change-message-info[ChangeMessageInfo] entities is r ] ---- +[[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 @@ -5415,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. diff --git a/java/com/google/gerrit/extensions/api/changes/ChangeApi.java b/java/com/google/gerrit/extensions/api/changes/ChangeApi.java index 9ccc7822f2..8b2d29b846 100644 --- a/java/com/google/gerrit/extensions/api/changes/ChangeApi.java +++ b/java/com/google/gerrit/extensions/api/changes/ChangeApi.java @@ -292,6 +292,17 @@ public interface ChangeApi { */ List 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; @@ -604,5 +615,10 @@ public interface ChangeApi { public List messages() throws RestApiException { throw new NotImplementedException(); } + + @Override + public ChangeMessageApi message(String id) throws RestApiException { + throw new NotImplementedException(); + } } } diff --git a/java/com/google/gerrit/extensions/api/changes/ChangeMessageApi.java b/java/com/google/gerrit/extensions/api/changes/ChangeMessageApi.java new file mode 100644 index 0000000000..eb2d2b9b5b --- /dev/null +++ b/java/com/google/gerrit/extensions/api/changes/ChangeMessageApi.java @@ -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(); + } + } +} diff --git a/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java b/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java index c25b5904a5..fb42ed0583 100644 --- a/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java +++ b/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java @@ -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; @@ -54,6 +55,7 @@ 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; @@ -113,6 +115,7 @@ 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; @@ -160,6 +163,7 @@ class ChangeApiImpl implements ChangeApi { Revisions revisions, ReviewerApiImpl.Factory reviewerApi, RevisionApiImpl.Factory revisionApi, + ChangeMessageApiImpl.Factory changeMessageApi, ChangeMessages changeMessages, SuggestChangeReviewers suggestReviewers, Abandon abandon, @@ -205,6 +209,7 @@ 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; @@ -723,4 +728,14 @@ class ChangeApiImpl implements ChangeApi { 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); + } + } } diff --git a/java/com/google/gerrit/server/api/changes/ChangeMessageApiImpl.java b/java/com/google/gerrit/server/api/changes/ChangeMessageApiImpl.java new file mode 100644 index 0000000000..988ac91a25 --- /dev/null +++ b/java/com/google/gerrit/server/api/changes/ChangeMessageApiImpl.java @@ -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); + } + } +} diff --git a/java/com/google/gerrit/server/api/changes/Module.java b/java/com/google/gerrit/server/api/changes/Module.java index e91d64ae73..0edd58ad38 100644 --- a/java/com/google/gerrit/server/api/changes/Module.java +++ b/java/com/google/gerrit/server/api/changes/Module.java @@ -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); } } diff --git a/java/com/google/gerrit/server/restapi/change/GetChangeMessage.java b/java/com/google/gerrit/server/restapi/change/GetChangeMessage.java new file mode 100644 index 0000000000..f55785d161 --- /dev/null +++ b/java/com/google/gerrit/server/restapi/change/GetChangeMessage.java @@ -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 { + @Override + public ChangeMessageInfo apply(ChangeMessageResource resource) { + return resource.getChangeMessage(); + } +} diff --git a/java/com/google/gerrit/server/restapi/change/Module.java b/java/com/google/gerrit/server/restapi/change/Module.java index 180e53f3b1..7955fa59d6 100644 --- a/java/com/google/gerrit/server/restapi/change/Module.java +++ b/java/com/google/gerrit/server/restapi/change/Module.java @@ -177,6 +177,7 @@ public class Module extends RestApiModule { 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); diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ChangeMessagesIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ChangeMessagesIT.java index 3e3c8fc612..d0b01b74d6 100644 --- a/javatests/com/google/gerrit/acceptance/rest/change/ChangeMessagesIT.java +++ b/javatests/com/google/gerrit/acceptance/rest/change/ChangeMessagesIT.java @@ -110,9 +110,18 @@ public class ChangeMessagesIT extends AbstractDaemonTest { assertThat(messages1).containsExactlyElementsIn(messages2).inOrder(); } - private int createOneChangeWithMultipleChangeMessagesInHistory() throws Exception { - // Creates the following commit history on the meta branch of the test change. + @Test + public void getOneChangeMessage() throws Exception { + int changeNum = createOneChangeWithMultipleChangeMessagesInHistory(); + List 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();