Merge changes I30886e35,I4bdc9a71
* changes: Document all options of list projects endpoint Add acceptance tests for list projects endpoint
This commit is contained in:
commit
4560488f1c
@ -52,22 +52,110 @@ by project name.
|
||||
}
|
||||
----
|
||||
|
||||
.Get all projects with their description
|
||||
****
|
||||
get::/projects/?d
|
||||
****
|
||||
[[project-options]]
|
||||
==== Project Options
|
||||
|
||||
Branch(b)::
|
||||
Limit the results to the projects having the specified branch and
|
||||
include the sha1 of the branch in the results.
|
||||
+
|
||||
Get projects that have a 'master' branch:
|
||||
+
|
||||
.Request
|
||||
----
|
||||
GET /projects/?b=master HTTP/1.0
|
||||
----
|
||||
+
|
||||
.Response
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
Content-Disposition: attachment
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
|
||||
)]}'
|
||||
{
|
||||
"some-project": {
|
||||
"id": "some-project",
|
||||
"branches": {
|
||||
"master": "c5ed9dfcbf002ca0e432d788dab6ca2387829ca7"
|
||||
}
|
||||
},
|
||||
"some-other-project": {
|
||||
"id": "some-other-project",
|
||||
"branches": {
|
||||
"master": "ef1c270142f9581ecf768f4193fc8f8a81102ec2"
|
||||
}
|
||||
},
|
||||
}
|
||||
----
|
||||
|
||||
Description(d)::
|
||||
Include project description in the results.
|
||||
+
|
||||
Get all the projects with their description:
|
||||
+
|
||||
.Request
|
||||
----
|
||||
GET /projects/?d HTTP/1.0
|
||||
----
|
||||
+
|
||||
.Response
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
Content-Disposition: attachment
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
|
||||
)]}'
|
||||
{
|
||||
"some-project": {
|
||||
"id": "some-project",
|
||||
"description": "Description of some project."
|
||||
},
|
||||
"some-other-project": {
|
||||
"id": "some-other-project",
|
||||
"description": "Description of some other project."
|
||||
}
|
||||
},
|
||||
}
|
||||
----
|
||||
|
||||
Limit(n)::
|
||||
Limit the number of projects to be included in the results.
|
||||
+
|
||||
Query the first project in the project list:
|
||||
+
|
||||
.Request
|
||||
----
|
||||
GET /projects/?n=1 HTTP/1.0
|
||||
----
|
||||
+
|
||||
.Response
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
Content-Disposition: attachment
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
|
||||
)]}'
|
||||
{
|
||||
"some-project": {
|
||||
"id": "some-project"
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
[[suggest-projects]]
|
||||
The `/projects/` URL also accepts a prefix string in the `p` parameter.
|
||||
This limits the results to those projects that start with the specified
|
||||
Prefix(p)::
|
||||
Limit the results to those projects that start with the specified
|
||||
prefix.
|
||||
+
|
||||
List all projects that start with `platform/`:
|
||||
|
||||
+
|
||||
.Request
|
||||
----
|
||||
GET /projects/?p=platform%2F HTTP/1.0
|
||||
----
|
||||
|
||||
+
|
||||
.Response
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
@ -84,22 +172,118 @@ List all projects that start with `platform/`:
|
||||
}
|
||||
}
|
||||
----
|
||||
+
|
||||
E.g. this feature can be used by suggestion client UI's to limit results.
|
||||
|
||||
The `/projects/` URL also accepts a limit integer in the `n` parameter.
|
||||
This limits the results to show `n` projects.
|
||||
|
||||
Query the first 25 projects in project list.
|
||||
Skip(S)::
|
||||
Skip the given number of projects from the beginning of the list.
|
||||
+
|
||||
Query the second project in the project list:
|
||||
+
|
||||
.Request
|
||||
----
|
||||
GET /projects/?n=25 HTTP/1.0
|
||||
GET /projects/?n=1&S=1 HTTP/1.0
|
||||
----
|
||||
+
|
||||
.Response
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
Content-Disposition: attachment
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
|
||||
)]}'
|
||||
{
|
||||
"some-other-project": {
|
||||
"id": "some-other-project"
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
The `/projects/` URL also accepts a start integer in the `S` parameter.
|
||||
The results will skip `S` projects from project list.
|
||||
|
||||
Query 25 projects starting from index 50.
|
||||
Substring(m)::
|
||||
Limit the results to those projects that match the specified substring.
|
||||
+
|
||||
List all projects that match substring `test/`:
|
||||
+
|
||||
.Request
|
||||
----
|
||||
GET /projects/?n=25&S=50 HTTP/1.0
|
||||
GET /projects/?m=test%2F HTTP/1.0
|
||||
----
|
||||
+
|
||||
.Response
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
Content-Disposition: attachment
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
|
||||
)]}'
|
||||
{
|
||||
"test/some-project": {
|
||||
"id": "test%2Fsome-project",
|
||||
},
|
||||
"some-path/test/some-other-project": {
|
||||
"id": "some-path%2Ftest%2Fsome-other-project",
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Tree(t)::
|
||||
Get projects inheritance in a tree-like format. This option does
|
||||
not work together with the branch option.
|
||||
+
|
||||
Get all the projects with tree option:
|
||||
+
|
||||
.Request
|
||||
----
|
||||
GET /projects/?t HTTP/1.0
|
||||
----
|
||||
+
|
||||
.Response
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
Content-Disposition: attachment
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
|
||||
)]}'
|
||||
{
|
||||
"All-Projects" {
|
||||
"id": "All-Projects"
|
||||
},
|
||||
"child-project": {
|
||||
"id": "child-project",
|
||||
"parent":"parent-project"
|
||||
},
|
||||
"parent-project": {
|
||||
"id": "parent-project",
|
||||
"parent":"All-Projects"
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Type(type)::
|
||||
Get projects with specified type: ALL, CODE, PERMISSIONS.
|
||||
+
|
||||
Get all the projects of type 'PERMISSIONS':
|
||||
+
|
||||
.Request
|
||||
----
|
||||
GET /projects/?type=PERMISSIONS HTTP/1.0
|
||||
----
|
||||
+
|
||||
.Response
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
Content-Disposition: attachment
|
||||
Content-Type: application/json;charset=UTF-8
|
||||
|
||||
)]}'
|
||||
{
|
||||
"All-Projects" {
|
||||
"id": "All-Projects"
|
||||
},
|
||||
"some-parent-project": {
|
||||
"id": "some-parent-project"
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
[[get-project]]
|
||||
|
@ -0,0 +1,211 @@
|
||||
// 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 com.google.gerrit.acceptance.GitUtil.createProject;
|
||||
import static com.google.gerrit.acceptance.rest.project.ProjectAssert.assertProjects;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||
import com.google.gerrit.acceptance.RestResponse;
|
||||
import com.google.gerrit.extensions.api.projects.ProjectInput;
|
||||
import com.google.gerrit.extensions.common.ProjectInfo;
|
||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.server.config.AllProjectsName;
|
||||
import com.google.gerrit.server.config.AllUsersName;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import com.jcraft.jsch.JSchException;
|
||||
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
public class ListProjectsIT extends AbstractDaemonTest {
|
||||
|
||||
@Inject
|
||||
private AllProjectsName allProjects;
|
||||
|
||||
@Inject
|
||||
private AllUsersName allUsers;
|
||||
|
||||
@Test
|
||||
public void listProjects() throws IOException, JSchException {
|
||||
Project.NameKey someProject = new Project.NameKey("some-project");
|
||||
createProject(sshSession, someProject.get());
|
||||
|
||||
RestResponse r = GET("/projects/");
|
||||
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||
Map<String, ProjectInfo> result = toProjectInfoMap(r);
|
||||
assertProjects(Arrays.asList(allUsers, someProject, project),
|
||||
result.values());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listProjectsWithBranch() throws IOException, JSchException {
|
||||
RestResponse r = GET("/projects/?b=master");
|
||||
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||
Map<String, ProjectInfo> result = toProjectInfoMap(r);
|
||||
assertNotNull(result.get(project.get()));
|
||||
assertNotNull(result.get(project.get()).branches);
|
||||
assertEquals(1, result.get(project.get()).branches.size());
|
||||
assertNotNull(result.get(project.get()).branches.get("master"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listProjectWithDescription() throws RestApiException, IOException {
|
||||
ProjectInput projectInput = new ProjectInput();
|
||||
projectInput.name = "some-project";
|
||||
projectInput.description = "Description of some-project";
|
||||
gApi.projects().name(projectInput.name).create(projectInput);
|
||||
|
||||
// description not be included in the results by default.
|
||||
RestResponse r = GET("/projects/");
|
||||
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||
Map<String, ProjectInfo> result = toProjectInfoMap(r);
|
||||
assertNotNull(result.get(projectInput.name));
|
||||
assertNull(result.get(projectInput.name).description);
|
||||
|
||||
r = GET("/projects/?d");
|
||||
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||
result = toProjectInfoMap(r);
|
||||
assertNotNull(result.get(projectInput.name));
|
||||
assertEquals(projectInput.description,
|
||||
result.get(projectInput.name).description);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listProjectsWithLimit() throws IOException, JSchException {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
createProject(sshSession, new Project.NameKey("someProject" + i).get());
|
||||
}
|
||||
|
||||
RestResponse r = GET("/projects/");
|
||||
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||
Map<String, ProjectInfo> result = toProjectInfoMap(r);
|
||||
assertEquals(7, result.size()); // 5 plus 2 existing projects: p and
|
||||
// All-Users
|
||||
|
||||
r = GET("/projects/?n=2");
|
||||
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||
result = toProjectInfoMap(r);
|
||||
assertEquals(2, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listProjectsWithPrefix() throws IOException, JSchException {
|
||||
Project.NameKey someProject = new Project.NameKey("some-project");
|
||||
createProject(sshSession, someProject.get());
|
||||
Project.NameKey someOtherProject =
|
||||
new Project.NameKey("some-other-project");
|
||||
createProject(sshSession, someOtherProject.get());
|
||||
Project.NameKey projectAwesome = new Project.NameKey("project-awesome");
|
||||
createProject(sshSession, projectAwesome.get());
|
||||
|
||||
RestResponse r = GET("/projects/?p=some");
|
||||
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||
Map<String, ProjectInfo> result = toProjectInfoMap(r);
|
||||
assertProjects(Arrays.asList(someProject, someOtherProject),
|
||||
result.values());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listProjectsWithSkip() throws IOException, JSchException {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
createProject(sshSession, new Project.NameKey("someProject" + i).get());
|
||||
}
|
||||
|
||||
RestResponse r = GET("/projects/");
|
||||
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||
Map<String, ProjectInfo> result = toProjectInfoMap(r);
|
||||
assertEquals(7, result.size()); // 5 plus 2 existing projects: p and
|
||||
// All-Users
|
||||
|
||||
r = GET("/projects/?S=6");
|
||||
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||
result = toProjectInfoMap(r);
|
||||
assertEquals(1, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listProjectsWithSubstring() throws IOException, JSchException {
|
||||
Project.NameKey someProject = new Project.NameKey("some-project");
|
||||
createProject(sshSession, someProject.get());
|
||||
Project.NameKey someOtherProject =
|
||||
new Project.NameKey("some-other-project");
|
||||
createProject(sshSession, someOtherProject.get());
|
||||
Project.NameKey projectAwesome = new Project.NameKey("project-awesome");
|
||||
createProject(sshSession, projectAwesome.get());
|
||||
|
||||
RestResponse r = GET("/projects/?m=some");
|
||||
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||
Map<String, ProjectInfo> result = toProjectInfoMap(r);
|
||||
assertProjects(
|
||||
Arrays.asList(someProject, someOtherProject, projectAwesome),
|
||||
result.values());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listProjectsWithTree() throws IOException, JSchException {
|
||||
Project.NameKey someParentProject =
|
||||
new Project.NameKey("some-parent-project");
|
||||
createProject(sshSession, someParentProject.get());
|
||||
Project.NameKey someChildProject =
|
||||
new Project.NameKey("some-child-project");
|
||||
createProject(sshSession, someChildProject.get(), someParentProject);
|
||||
|
||||
RestResponse r = GET("/projects/?tree");
|
||||
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||
Map<String, ProjectInfo> result = toProjectInfoMap(r);
|
||||
assertNotNull(result.get(someChildProject.get()));
|
||||
assertEquals(someParentProject.get(),
|
||||
result.get(someChildProject.get()).parent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listProjectWithType() throws RestApiException, IOException {
|
||||
RestResponse r = GET("/projects/?type=PERMISSIONS");
|
||||
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||
Map<String, ProjectInfo> result = toProjectInfoMap(r);
|
||||
assertEquals(1, result.size());
|
||||
assertNotNull(result.get(allProjects.get()));
|
||||
|
||||
r = GET("/projects/?type=ALL");
|
||||
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||
result = toProjectInfoMap(r);
|
||||
assertEquals(3, result.size());
|
||||
assertProjects(Arrays.asList(allProjects, allUsers, project),
|
||||
result.values());
|
||||
}
|
||||
|
||||
private static Map<String, ProjectInfo> toProjectInfoMap(RestResponse r)
|
||||
throws IOException {
|
||||
Map<String, ProjectInfo> result =
|
||||
newGson().fromJson(r.getReader(),
|
||||
new TypeToken<Map<String, ProjectInfo>>() {}.getType());
|
||||
return result;
|
||||
}
|
||||
|
||||
private RestResponse GET(String endpoint) throws IOException {
|
||||
return adminSession.get(endpoint);
|
||||
}
|
||||
}
|
@ -27,18 +27,20 @@ import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.server.project.ProjectState;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
public class ProjectAssert {
|
||||
|
||||
public static void assertProjects(Iterable<Project.NameKey> expected,
|
||||
List<ProjectInfo> actual) {
|
||||
Collection<ProjectInfo> actual) {
|
||||
for (final Project.NameKey p : expected) {
|
||||
ProjectInfo info = Iterables.find(actual, new Predicate<ProjectInfo>() {
|
||||
@Override
|
||||
public boolean apply(ProjectInfo info) {
|
||||
return new Project.NameKey(info.name).equals(p);
|
||||
// 'name' is not set if returned in a map, use the id instead.
|
||||
return new Project.NameKey(info.name != null ? info.name : Url
|
||||
.decode(info.id)).equals(p);
|
||||
}}, null);
|
||||
assertNotNull("missing project: " + p, info);
|
||||
actual.remove(info);
|
||||
|
Loading…
Reference in New Issue
Block a user