Add REST endpoint to get an arbitrary commit from a project
Bug: issue 2604 Change-Id: I138e60c5291d61c379e947ea26b0fd9d5555c743 Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
This commit is contained in:

committed by
Edwin Kempin

parent
990662d0b8
commit
1b99360cc7
@@ -972,6 +972,59 @@ describes the child project.
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
[[commit-endpoints]]
|
||||||
|
== Commit Endpoints
|
||||||
|
|
||||||
|
[[get-commit]]
|
||||||
|
=== Get Commit
|
||||||
|
--
|
||||||
|
'GET /projects/link:#project-name[\{project-name\}]/commits/link:#commit-id[\{commit-id\}]'
|
||||||
|
--
|
||||||
|
|
||||||
|
Retrieves a commit of a project.
|
||||||
|
|
||||||
|
The commit must be visible to the caller.
|
||||||
|
|
||||||
|
.Request
|
||||||
|
----
|
||||||
|
GET /projects/work%2Fmy-project/commits/a8a477efffbbf3b44169bb9a1d3a334cbbd9aa96 HTTP/1.0
|
||||||
|
----
|
||||||
|
|
||||||
|
As response a link:rest-api-changes.html#commit-info[CommitInfo] entity
|
||||||
|
is returned that describes the commit.
|
||||||
|
|
||||||
|
.Response
|
||||||
|
----
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Content-Disposition: attachment
|
||||||
|
Content-Type: application/json;charset=UTF-8
|
||||||
|
|
||||||
|
)]}'
|
||||||
|
{
|
||||||
|
"commit": "184ebe53805e102605d11f6b143486d15c23a09c",
|
||||||
|
"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 ..."
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
[[dashboard-endpoints]]
|
[[dashboard-endpoints]]
|
||||||
== Dashboard Endpoints
|
== Dashboard Endpoints
|
||||||
|
|
||||||
@@ -1199,6 +1252,10 @@ requests.
|
|||||||
The name of a branch or `HEAD`. The prefix `refs/heads/` can be
|
The name of a branch or `HEAD`. The prefix `refs/heads/` can be
|
||||||
omitted.
|
omitted.
|
||||||
|
|
||||||
|
[[commit-id]]
|
||||||
|
=== \{commit-id\}
|
||||||
|
Commit ID.
|
||||||
|
|
||||||
[[dashboard-id]]
|
[[dashboard-id]]
|
||||||
=== \{dashboard-id\}
|
=== \{dashboard-id\}
|
||||||
The ID of a dashboard in the format '<ref>:<path>'.
|
The ID of a dashboard in the format '<ref>:<path>'.
|
||||||
|
@@ -0,0 +1,111 @@
|
|||||||
|
// Copyright (C) 2014 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.rest.project;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||||
|
import com.google.gerrit.acceptance.RestResponse;
|
||||||
|
import com.google.gerrit.common.data.Permission;
|
||||||
|
import com.google.gerrit.extensions.common.CommitInfo;
|
||||||
|
import com.google.gerrit.extensions.restapi.IdString;
|
||||||
|
import com.google.gerrit.reviewdb.client.RefNames;
|
||||||
|
import com.google.gerrit.server.config.AllProjectsName;
|
||||||
|
import com.google.gerrit.server.git.MetaDataUpdate;
|
||||||
|
import com.google.gerrit.server.git.ProjectConfig;
|
||||||
|
import com.google.gerrit.server.project.ListBranches.BranchInfo;
|
||||||
|
import com.google.gerrit.server.project.ProjectCache;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class GetCommitIT extends AbstractDaemonTest {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ProjectCache projectCache;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private AllProjectsName allProjects;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private MetaDataUpdate.Server metaDataUpdateFactory;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getCommit() throws IOException {
|
||||||
|
RestResponse r =
|
||||||
|
adminSession.get("/projects/" + project.get() + "/branches/"
|
||||||
|
+ IdString.fromDecoded(RefNames.REFS_CONFIG).encoded());
|
||||||
|
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||||
|
BranchInfo branchInfo =
|
||||||
|
newGson().fromJson(r.getReader(), BranchInfo.class);
|
||||||
|
r.consume();
|
||||||
|
|
||||||
|
r = adminSession.get("/projects/" + project.get() + "/commits/"
|
||||||
|
+ branchInfo.revision);
|
||||||
|
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||||
|
CommitInfo commitInfo =
|
||||||
|
newGson().fromJson(r.getReader(), CommitInfo.class);
|
||||||
|
assertEquals(branchInfo.revision, commitInfo.commit);
|
||||||
|
assertEquals("Created project", commitInfo.subject);
|
||||||
|
assertEquals("Created project\n", commitInfo.message);
|
||||||
|
assertNotNull(commitInfo.author);
|
||||||
|
assertEquals("Administrator", commitInfo.author.name);
|
||||||
|
assertNotNull(commitInfo.committer);
|
||||||
|
assertEquals("Gerrit Code Review", commitInfo.committer.name);
|
||||||
|
assertTrue(commitInfo.parents.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getNonExistingCommit_NotFound() throws IOException {
|
||||||
|
RestResponse r = adminSession.get("/projects/" + project.get() + "/commits/"
|
||||||
|
+ ObjectId.zeroId().name());
|
||||||
|
assertEquals(HttpStatus.SC_NOT_FOUND, r.getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getNonVisibleCommit_NotFound() throws IOException {
|
||||||
|
RestResponse r =
|
||||||
|
adminSession.get("/projects/" + project.get() + "/branches/"
|
||||||
|
+ IdString.fromDecoded(RefNames.REFS_CONFIG).encoded());
|
||||||
|
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||||
|
BranchInfo branchInfo =
|
||||||
|
newGson().fromJson(r.getReader(), BranchInfo.class);
|
||||||
|
r.consume();
|
||||||
|
|
||||||
|
ProjectConfig cfg = projectCache.checkedGet(allProjects).getConfig();
|
||||||
|
cfg.getAccessSection("refs/*", false).removePermission(Permission.READ);
|
||||||
|
saveProjectConfig(cfg);
|
||||||
|
projectCache.evict(cfg.getProject());
|
||||||
|
|
||||||
|
r = adminSession.get("/projects/" + project.get() + "/commits/"
|
||||||
|
+ branchInfo.revision);
|
||||||
|
assertEquals(HttpStatus.SC_NOT_FOUND, r.getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveProjectConfig(ProjectConfig cfg) throws IOException {
|
||||||
|
MetaDataUpdate md = metaDataUpdateFactory.create(allProjects);
|
||||||
|
try {
|
||||||
|
cfg.commit(md);
|
||||||
|
} finally {
|
||||||
|
md.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
// Copyright (C) 2014 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.project;
|
||||||
|
|
||||||
|
import com.google.gerrit.extensions.restapi.RestView;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
|
|
||||||
|
public class CommitResource extends ProjectResource {
|
||||||
|
public static final TypeLiteral<RestView<CommitResource>> COMMIT_KIND =
|
||||||
|
new TypeLiteral<RestView<CommitResource>>() {};
|
||||||
|
|
||||||
|
private final RevCommit commit;
|
||||||
|
|
||||||
|
public CommitResource(ProjectControl control, RevCommit commit) {
|
||||||
|
super(control);
|
||||||
|
this.commit = commit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RevCommit getCommit() {
|
||||||
|
return commit;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,89 @@
|
|||||||
|
// Copyright (C) 2014 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.project;
|
||||||
|
|
||||||
|
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.git.GitRepositoryManager;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
||||||
|
import org.eclipse.jgit.errors.MissingObjectException;
|
||||||
|
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 java.io.IOException;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class CommitsCollection implements
|
||||||
|
ChildCollection<ProjectResource, CommitResource> {
|
||||||
|
private final DynamicMap<RestView<CommitResource>> views;
|
||||||
|
private final GitRepositoryManager repoManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public CommitsCollection(DynamicMap<RestView<CommitResource>> views,
|
||||||
|
GitRepositoryManager repoManager) {
|
||||||
|
this.views = views;
|
||||||
|
this.repoManager = repoManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RestView<ProjectResource> list() throws ResourceNotFoundException {
|
||||||
|
throw new ResourceNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommitResource parse(ProjectResource parent, IdString id)
|
||||||
|
throws ResourceNotFoundException, IOException {
|
||||||
|
ObjectId objectId;
|
||||||
|
try {
|
||||||
|
objectId = ObjectId.fromString(id.get());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new ResourceNotFoundException(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Repository repo = repoManager.openRepository(parent.getNameKey());
|
||||||
|
try {
|
||||||
|
RevWalk rw = new RevWalk(repo);
|
||||||
|
try {
|
||||||
|
RevCommit commit = rw.parseCommit(objectId);
|
||||||
|
if (!parent.getControl().canReadCommit(rw, commit)) {
|
||||||
|
throw new ResourceNotFoundException(id);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < commit.getParentCount(); i++) {
|
||||||
|
rw.parseCommit(commit.getParent(i));
|
||||||
|
}
|
||||||
|
return new CommitResource(parent.getControl(), commit);
|
||||||
|
} catch (MissingObjectException | IncorrectObjectTypeException e) {
|
||||||
|
throw new ResourceNotFoundException(id);
|
||||||
|
} finally {
|
||||||
|
rw.release();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
repo.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DynamicMap<RestView<CommitResource>> views() {
|
||||||
|
return views;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,64 @@
|
|||||||
|
// Copyright (C) 2014 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.project;
|
||||||
|
|
||||||
|
import com.google.gerrit.extensions.common.CommitInfo;
|
||||||
|
import com.google.gerrit.extensions.common.GitPerson;
|
||||||
|
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.PersonIdent;
|
||||||
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class GetCommit implements RestReadView<CommitResource> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommitInfo apply(CommitResource rsrc) {
|
||||||
|
RevCommit c = rsrc.getCommit();
|
||||||
|
CommitInfo info = toCommitInfo(c);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CommitInfo toCommitInfo(RevCommit commit) {
|
||||||
|
CommitInfo info = new CommitInfo();
|
||||||
|
info.commit = commit.getName();
|
||||||
|
info.author = toGitPerson(commit.getAuthorIdent());
|
||||||
|
info.committer = toGitPerson(commit.getCommitterIdent());
|
||||||
|
info.subject = commit.getShortMessage();
|
||||||
|
info.message = commit.getFullMessage();
|
||||||
|
info.parents = new ArrayList<>(commit.getParentCount());
|
||||||
|
for (int i = 0; i < commit.getParentCount(); i++) {
|
||||||
|
RevCommit p = commit.getParent(i);
|
||||||
|
CommitInfo parentInfo = new CommitInfo();
|
||||||
|
parentInfo.commit = p.getName();
|
||||||
|
parentInfo.subject = p.getShortMessage();
|
||||||
|
info.parents.add(parentInfo);
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GitPerson toGitPerson(PersonIdent ident) {
|
||||||
|
GitPerson gp = new GitPerson();
|
||||||
|
gp.name = ident.getName();
|
||||||
|
gp.email = ident.getEmailAddress();
|
||||||
|
gp.date = new Timestamp(ident.getWhen().getTime());
|
||||||
|
gp.tz = ident.getTimeZoneOffset();
|
||||||
|
return gp;
|
||||||
|
}
|
||||||
|
}
|
@@ -16,9 +16,10 @@ package com.google.gerrit.server.project;
|
|||||||
|
|
||||||
import static com.google.gerrit.server.project.BranchResource.BRANCH_KIND;
|
import static com.google.gerrit.server.project.BranchResource.BRANCH_KIND;
|
||||||
import static com.google.gerrit.server.project.ChildProjectResource.CHILD_PROJECT_KIND;
|
import static com.google.gerrit.server.project.ChildProjectResource.CHILD_PROJECT_KIND;
|
||||||
|
import static com.google.gerrit.server.project.CommitResource.COMMIT_KIND;
|
||||||
import static com.google.gerrit.server.project.DashboardResource.DASHBOARD_KIND;
|
import static com.google.gerrit.server.project.DashboardResource.DASHBOARD_KIND;
|
||||||
import static com.google.gerrit.server.project.ProjectResource.PROJECT_KIND;
|
|
||||||
import static com.google.gerrit.server.project.FileResource.FILE_KIND;
|
import static com.google.gerrit.server.project.FileResource.FILE_KIND;
|
||||||
|
import static com.google.gerrit.server.project.ProjectResource.PROJECT_KIND;
|
||||||
|
|
||||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||||
import com.google.gerrit.extensions.restapi.RestApiModule;
|
import com.google.gerrit.extensions.restapi.RestApiModule;
|
||||||
@@ -35,6 +36,7 @@ public class Module extends RestApiModule {
|
|||||||
DynamicMap.mapOf(binder(), BRANCH_KIND);
|
DynamicMap.mapOf(binder(), BRANCH_KIND);
|
||||||
DynamicMap.mapOf(binder(), DASHBOARD_KIND);
|
DynamicMap.mapOf(binder(), DASHBOARD_KIND);
|
||||||
DynamicMap.mapOf(binder(), FILE_KIND);
|
DynamicMap.mapOf(binder(), FILE_KIND);
|
||||||
|
DynamicMap.mapOf(binder(), COMMIT_KIND);
|
||||||
|
|
||||||
put(PROJECT_KIND).to(PutProject.class);
|
put(PROJECT_KIND).to(PutProject.class);
|
||||||
get(PROJECT_KIND).to(GetProject.class);
|
get(PROJECT_KIND).to(GetProject.class);
|
||||||
@@ -63,6 +65,9 @@ public class Module extends RestApiModule {
|
|||||||
child(BRANCH_KIND, "files").to(FilesCollection.class);
|
child(BRANCH_KIND, "files").to(FilesCollection.class);
|
||||||
get(FILE_KIND, "content").to(GetContent.class);
|
get(FILE_KIND, "content").to(GetContent.class);
|
||||||
|
|
||||||
|
child(PROJECT_KIND, "commits").to(CommitsCollection.class);
|
||||||
|
get(COMMIT_KIND).to(GetCommit.class);
|
||||||
|
|
||||||
child(PROJECT_KIND, "dashboards").to(DashboardsCollection.class);
|
child(PROJECT_KIND, "dashboards").to(DashboardsCollection.class);
|
||||||
get(DASHBOARD_KIND).to(GetDashboard.class);
|
get(DASHBOARD_KIND).to(GetDashboard.class);
|
||||||
put(DASHBOARD_KIND).to(SetDashboard.class);
|
put(DASHBOARD_KIND).to(SetDashboard.class);
|
||||||
|
Reference in New Issue
Block a user