Merge "Add REST endpoint to list the commits that are integrated by a merge"
This commit is contained in:
@@ -2572,6 +2572,60 @@ describes the revision.
|
||||
Adding query parameter `links` (for example `/changes/.../commit?links`)
|
||||
returns a link:#commit-info[CommitInfo] with the additional field `web_links`.
|
||||
|
||||
[[get-merge-list]]
|
||||
=== Get Merge List
|
||||
--
|
||||
'GET /changes/link:#change-id[\{change-id\}]/revisions/link:#revision-id[\{revision-id\}]/mergelist'
|
||||
--
|
||||
|
||||
Returns the list of commits that are being integrated into a target
|
||||
branch by a merge commit. By default the first parent is assumed to be
|
||||
uninteresting. By using the `parent` option another parent can be set
|
||||
as uninteresting (parents are 1-based).
|
||||
|
||||
The list of commits is returned as a list of
|
||||
link:#commit-info[CommitInfo] entities. Web links are only included if
|
||||
the `links` option was set.
|
||||
|
||||
.Request
|
||||
----
|
||||
GET /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/revisions/7e30d802b890ec8d0be45b1cc2a8ef092bcfc858/mergelist HTTP/1.0
|
||||
----
|
||||
|
||||
.Response
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
Content-Disposition: attachment
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
|
||||
)]}'
|
||||
[
|
||||
{
|
||||
"commit": "674ac754f91e64a0efb8087e59a176484bd534d1",
|
||||
"parents": [
|
||||
{
|
||||
"commit": "1eee2c9d8f352483781e772f35dc586a69ff5646",
|
||||
"subject": "Migrate contributor agreements to All-Projects."
|
||||
}
|
||||
],
|
||||
"author": {
|
||||
"name": "Shawn O. Pearce",
|
||||
"email": "sop@google.com",
|
||||
"date": "2012-04-24 18:08:08.000000000",
|
||||
"tz": -420
|
||||
},
|
||||
"committer": {
|
||||
"name": "Shawn O. Pearce",
|
||||
"email": "sop@google.com",
|
||||
"date": "2012-04-24 18:08:08.000000000",
|
||||
"tz": -420
|
||||
},
|
||||
"subject": "Use an EventBus to manage star icons",
|
||||
"message": "Use an EventBus to manage star icons\n\nImage widgets that need to ..."
|
||||
}
|
||||
]
|
||||
----
|
||||
|
||||
[[get-revision-actions]]
|
||||
=== Get Revision Actions
|
||||
--
|
||||
|
@@ -0,0 +1,80 @@
|
||||
// Copyright (C) 2016 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.acceptance.api.change;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.eclipse.jgit.lib.Constants.HEAD;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||
import com.google.gerrit.acceptance.NoHttpd;
|
||||
import com.google.gerrit.acceptance.PushOneCommit;
|
||||
import com.google.gerrit.extensions.common.CommitInfo;
|
||||
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@NoHttpd
|
||||
public class GetMergeListIT extends AbstractDaemonTest {
|
||||
|
||||
@Test
|
||||
public void getMergeList() throws Exception {
|
||||
ObjectId initial = repo().exactRef(HEAD).getLeaf().getObjectId();
|
||||
|
||||
PushOneCommit.Result gp1 = pushFactory
|
||||
.create(db, admin.getIdent(), testRepo, "grand parent 1",
|
||||
ImmutableMap.of("foo", "foo-1.1", "bar", "bar-1.1"))
|
||||
.to("refs/for/master");
|
||||
|
||||
PushOneCommit.Result p1 = pushFactory
|
||||
.create(db, admin.getIdent(), testRepo, "parent 1",
|
||||
ImmutableMap.of("foo", "foo-1.2", "bar", "bar-1.2"))
|
||||
.to("refs/for/master");
|
||||
|
||||
// reset HEAD in order to create a sibling of the first change
|
||||
testRepo.reset(initial);
|
||||
|
||||
PushOneCommit.Result gp2 = pushFactory
|
||||
.create(db, admin.getIdent(), testRepo, "grand parent 1",
|
||||
ImmutableMap.of("foo", "foo-2.1", "bar", "bar-2.1"))
|
||||
.to("refs/for/master");
|
||||
|
||||
PushOneCommit.Result p2 = pushFactory
|
||||
.create(db, admin.getIdent(), testRepo, "parent 2",
|
||||
ImmutableMap.of("foo", "foo-2.2", "bar", "bar-2.2"))
|
||||
.to("refs/for/master");
|
||||
|
||||
PushOneCommit m = pushFactory.create(db, admin.getIdent(), testRepo,
|
||||
"merge", ImmutableMap.of("foo", "foo-1", "bar", "bar-2"));
|
||||
m.setParents(ImmutableList.of(p1.getCommit(), p2.getCommit()));
|
||||
PushOneCommit.Result result = m.to("refs/for/master");
|
||||
result.assertOkStatus();
|
||||
|
||||
List<CommitInfo> mergeList =
|
||||
gApi.changes().id(result.getChangeId()).current().getMergeList().get();
|
||||
assertThat(mergeList).hasSize(2);
|
||||
assertThat(mergeList.get(0).commit).isEqualTo(p2.getCommit().name());
|
||||
assertThat(mergeList.get(1).commit).isEqualTo(gp2.getCommit().name());
|
||||
|
||||
mergeList = gApi.changes().id(result.getChangeId()).current().getMergeList()
|
||||
.withUninterestingParent(2).get();
|
||||
assertThat(mergeList).hasSize(2);
|
||||
assertThat(mergeList.get(0).commit).isEqualTo(p1.getCommit().name());
|
||||
assertThat(mergeList.get(1).commit).isEqualTo(gp1.getCommit().name());
|
||||
}
|
||||
}
|
@@ -17,6 +17,7 @@ package com.google.gerrit.extensions.api.changes;
|
||||
import com.google.gerrit.extensions.client.SubmitType;
|
||||
import com.google.gerrit.extensions.common.ActionInfo;
|
||||
import com.google.gerrit.extensions.common.CommentInfo;
|
||||
import com.google.gerrit.extensions.common.CommitInfo;
|
||||
import com.google.gerrit.extensions.common.FileInfo;
|
||||
import com.google.gerrit.extensions.common.MergeableInfo;
|
||||
import com.google.gerrit.extensions.common.TestSubmitRuleInput;
|
||||
@@ -72,6 +73,33 @@ public interface RevisionApi {
|
||||
SubmitType submitType() throws RestApiException;
|
||||
SubmitType testSubmitType(TestSubmitRuleInput in) throws RestApiException;
|
||||
|
||||
MergeListRequest getMergeList() throws RestApiException;
|
||||
|
||||
abstract class MergeListRequest {
|
||||
private boolean addLinks;
|
||||
private int uninterestingParent = 1;
|
||||
|
||||
public abstract List<CommitInfo> get() throws RestApiException;
|
||||
|
||||
public MergeListRequest withLinks() {
|
||||
this.addLinks = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MergeListRequest withUninterestingParent(int uninterestingParent) {
|
||||
this.uninterestingParent = uninterestingParent;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean getAddLinks() {
|
||||
return addLinks;
|
||||
}
|
||||
|
||||
public int getUninterestingParent() {
|
||||
return uninterestingParent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A default implementation which allows source compatibility
|
||||
* when adding new methods to the interface.
|
||||
@@ -217,5 +245,10 @@ public interface RevisionApi {
|
||||
throws RestApiException {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MergeListRequest getMergeList() throws RestApiException {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -30,6 +30,7 @@ import com.google.gerrit.extensions.api.changes.SubmitInput;
|
||||
import com.google.gerrit.extensions.client.SubmitType;
|
||||
import com.google.gerrit.extensions.common.ActionInfo;
|
||||
import com.google.gerrit.extensions.common.CommentInfo;
|
||||
import com.google.gerrit.extensions.common.CommitInfo;
|
||||
import com.google.gerrit.extensions.common.FileInfo;
|
||||
import com.google.gerrit.extensions.common.MergeableInfo;
|
||||
import com.google.gerrit.extensions.common.TestSubmitRuleInput;
|
||||
@@ -44,6 +45,7 @@ import com.google.gerrit.server.change.DeleteDraftPatchSet;
|
||||
import com.google.gerrit.server.change.DraftComments;
|
||||
import com.google.gerrit.server.change.FileResource;
|
||||
import com.google.gerrit.server.change.Files;
|
||||
import com.google.gerrit.server.change.GetMergeList;
|
||||
import com.google.gerrit.server.change.GetPatch;
|
||||
import com.google.gerrit.server.change.GetRevisionActions;
|
||||
import com.google.gerrit.server.change.ListRevisionComments;
|
||||
@@ -63,6 +65,7 @@ import com.google.gerrit.server.patch.PatchListNotAvailableException;
|
||||
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
@@ -105,6 +108,7 @@ class RevisionApiImpl implements RevisionApi {
|
||||
private final GetRevisionActions revisionActions;
|
||||
private final TestSubmitType testSubmitType;
|
||||
private final TestSubmitType.Get getSubmitType;
|
||||
private final Provider<GetMergeList> getMergeList;
|
||||
|
||||
@Inject
|
||||
RevisionApiImpl(GitRepositoryManager repoManager,
|
||||
@@ -133,6 +137,7 @@ class RevisionApiImpl implements RevisionApi {
|
||||
GetRevisionActions revisionActions,
|
||||
TestSubmitType testSubmitType,
|
||||
TestSubmitType.Get getSubmitType,
|
||||
Provider<GetMergeList> getMergeList,
|
||||
@Assisted RevisionResource r) {
|
||||
this.repoManager = repoManager;
|
||||
this.changes = changes;
|
||||
@@ -160,6 +165,7 @@ class RevisionApiImpl implements RevisionApi {
|
||||
this.revisionActions = revisionActions;
|
||||
this.testSubmitType = testSubmitType;
|
||||
this.getSubmitType = getSubmitType;
|
||||
this.getMergeList = getMergeList;
|
||||
this.revision = r;
|
||||
}
|
||||
|
||||
@@ -428,4 +434,21 @@ class RevisionApiImpl implements RevisionApi {
|
||||
throw new RestApiException("Cannot test submit type", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MergeListRequest getMergeList() throws RestApiException {
|
||||
return new MergeListRequest() {
|
||||
@Override
|
||||
public List<CommitInfo> get() throws RestApiException {
|
||||
try {
|
||||
GetMergeList gml = getMergeList.get();
|
||||
gml.setUninterestingParent(getUninterestingParent());
|
||||
gml.setAddLinks(getAddLinks());
|
||||
return gml.apply(revision).value();
|
||||
} catch (IOException e) {
|
||||
throw new RestApiException("Cannot get merge list", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -35,7 +35,7 @@ public class GetCommit implements RestReadView<RevisionResource> {
|
||||
private final GitRepositoryManager repoManager;
|
||||
private final ChangeJson.Factory json;
|
||||
|
||||
@Option(name = "--links", usage = "Add weblinks")
|
||||
@Option(name = "--links", usage = "Include weblinks")
|
||||
private boolean addLinks;
|
||||
|
||||
@Inject
|
||||
|
@@ -0,0 +1,105 @@
|
||||
// Copyright (C) 2016 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.common.collect.ImmutableList;
|
||||
import com.google.gerrit.extensions.common.CommitInfo;
|
||||
import com.google.gerrit.extensions.restapi.BadRequestException;
|
||||
import com.google.gerrit.extensions.restapi.CacheControl;
|
||||
import com.google.gerrit.extensions.restapi.Response;
|
||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import org.kohsuke.args4j.Option;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class GetMergeList implements RestReadView<RevisionResource> {
|
||||
private final GitRepositoryManager repoManager;
|
||||
private final ChangeJson.Factory json;
|
||||
|
||||
@Option(name = "--parent", usage = "Uninteresting parent (1-based, default = 1)")
|
||||
private int uninterestingParent = 1;
|
||||
|
||||
@Option(name = "--links", usage = "Include weblinks")
|
||||
private boolean addLinks;
|
||||
|
||||
@Inject
|
||||
GetMergeList(GitRepositoryManager repoManager, ChangeJson.Factory json) {
|
||||
this.repoManager = repoManager;
|
||||
this.json = json;
|
||||
}
|
||||
|
||||
public void setUninterestingParent(int uninterestingParent) {
|
||||
this.uninterestingParent = uninterestingParent;
|
||||
}
|
||||
|
||||
public void setAddLinks(boolean addLinks) {
|
||||
this.addLinks = addLinks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<List<CommitInfo>> apply(RevisionResource rsrc)
|
||||
throws BadRequestException, IOException {
|
||||
List<CommitInfo> result = new ArrayList<>();
|
||||
Project.NameKey p = rsrc.getChange().getProject();
|
||||
try (Repository repo = repoManager.openRepository(p);
|
||||
RevWalk rw = new RevWalk(repo)) {
|
||||
String rev = rsrc.getPatchSet().getRevision().get();
|
||||
RevCommit commit = rw.parseCommit(ObjectId.fromString(rev));
|
||||
rw.parseBody(commit);
|
||||
|
||||
if (uninterestingParent < 1
|
||||
|| uninterestingParent > commit.getParentCount()) {
|
||||
throw new BadRequestException("No such parent: " + uninterestingParent);
|
||||
}
|
||||
|
||||
if (commit.getParentCount() < 2) {
|
||||
return Response.<List<CommitInfo>> ok(ImmutableList.<CommitInfo> of());
|
||||
}
|
||||
|
||||
for (int parent = 0; parent < commit.getParentCount(); parent++) {
|
||||
if (parent == uninterestingParent - 1) {
|
||||
rw.markUninteresting(commit.getParent(parent));
|
||||
} else {
|
||||
rw.markStart(commit.getParent(parent));
|
||||
}
|
||||
}
|
||||
|
||||
ChangeJson changeJson = json.create(ChangeJson.NO_OPTIONS);
|
||||
RevCommit c;
|
||||
while ((c = rw.next()) != null) {
|
||||
CommitInfo info =
|
||||
changeJson.toCommit(rsrc.getControl(), rw, c, addLinks, true);
|
||||
result.add(info);
|
||||
}
|
||||
}
|
||||
|
||||
Response<List<CommitInfo>> r = Response.ok(result);
|
||||
if (rsrc.isCacheable()) {
|
||||
r.caching(CacheControl.PRIVATE(7, TimeUnit.DAYS));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
@@ -100,6 +100,7 @@ public class Module extends RestApiModule {
|
||||
post(REVISION_KIND, "test.submit_rule").to(TestSubmitRule.class);
|
||||
post(REVISION_KIND, "test.submit_type").to(TestSubmitType.class);
|
||||
get(REVISION_KIND, "archive").to(GetArchive.class);
|
||||
get(REVISION_KIND, "mergelist").to(GetMergeList.class);
|
||||
|
||||
child(REVISION_KIND, "drafts").to(DraftComments.class);
|
||||
put(REVISION_KIND, "drafts").to(CreateDraftComment.class);
|
||||
|
Reference in New Issue
Block a user