ListProjects: Allow to filter list by project state
Bug: Issue 7747 Change-Id: Ibf39b408fce8e76a61706ae45da433faaf0391f2
This commit is contained in:
@@ -325,7 +325,8 @@ GET /projects/?type=PERMISSIONS HTTP/1.0
|
||||
----
|
||||
|
||||
All::
|
||||
Get all projects, including those whose state is "HIDDEN".
|
||||
Get all projects, including those whose state is "HIDDEN". May not be used
|
||||
together with the `state` option.
|
||||
+
|
||||
.Request
|
||||
----
|
||||
@@ -351,6 +352,30 @@ GET /projects/?all HTTP/1.0
|
||||
}
|
||||
----
|
||||
|
||||
State(s)::
|
||||
Get all projects with the given state. May not be used together with the
|
||||
`all` option.
|
||||
+
|
||||
.Request
|
||||
----
|
||||
GET /projects/?state=HIDDEN 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",
|
||||
"state": "HIDDEN"
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
[[query-projects]]
|
||||
=== Query Projects
|
||||
--
|
||||
|
@@ -14,6 +14,7 @@
|
||||
|
||||
package com.google.gerrit.extensions.api.projects;
|
||||
|
||||
import com.google.gerrit.extensions.client.ProjectState;
|
||||
import com.google.gerrit.extensions.common.ProjectInfo;
|
||||
import com.google.gerrit.extensions.restapi.NotImplementedException;
|
||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
@@ -94,6 +95,7 @@ public interface Projects {
|
||||
private boolean showTree;
|
||||
private boolean all;
|
||||
private FilterType type = FilterType.ALL;
|
||||
private ProjectState state = null;
|
||||
|
||||
public List<ProjectInfo> get() throws RestApiException {
|
||||
Map<String, ProjectInfo> map = getAsMap();
|
||||
@@ -158,6 +160,11 @@ public interface Projects {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ListRequest withState(ProjectState state) {
|
||||
this.state = state;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean getDescription() {
|
||||
return description;
|
||||
}
|
||||
@@ -197,6 +204,10 @@ public interface Projects {
|
||||
public boolean isAll() {
|
||||
return all;
|
||||
}
|
||||
|
||||
public ProjectState getState() {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -131,6 +131,8 @@ class ProjectsImpl implements Projects {
|
||||
|
||||
lp.setAll(request.isAll());
|
||||
|
||||
lp.setState(request.getState());
|
||||
|
||||
return lp.apply();
|
||||
}
|
||||
|
||||
|
@@ -190,6 +190,15 @@ public class ListProjects implements RestReadView<TopLevelResource> {
|
||||
this.all = all;
|
||||
}
|
||||
|
||||
@Option(
|
||||
name = "--state",
|
||||
aliases = {"-s"},
|
||||
usage = "filter by project state"
|
||||
)
|
||||
public void setState(com.google.gerrit.extensions.client.ProjectState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@Option(
|
||||
name = "--limit",
|
||||
aliases = {"-n"},
|
||||
@@ -249,6 +258,7 @@ public class ListProjects implements RestReadView<TopLevelResource> {
|
||||
private FilterType type = FilterType.ALL;
|
||||
private boolean showDescription;
|
||||
private boolean all;
|
||||
private com.google.gerrit.extensions.client.ProjectState state;
|
||||
private int limit;
|
||||
private int start;
|
||||
private String matchPrefix;
|
||||
@@ -318,6 +328,9 @@ public class ListProjects implements RestReadView<TopLevelResource> {
|
||||
|
||||
public SortedMap<String, ProjectInfo> display(@Nullable OutputStream displayOutputStream)
|
||||
throws BadRequestException, PermissionBackendException {
|
||||
if (all && state != null) {
|
||||
throw new BadRequestException("'all' and 'state' may not be used together");
|
||||
}
|
||||
if (groupUuid != null) {
|
||||
try {
|
||||
if (!groupControlFactory.controlFor(groupUuid).isVisible()) {
|
||||
@@ -349,9 +362,14 @@ public class ListProjects implements RestReadView<TopLevelResource> {
|
||||
try {
|
||||
for (Project.NameKey projectName : filter(perm)) {
|
||||
final ProjectState e = projectCache.get(projectName);
|
||||
if (e == null || (!all && e.getProject().getState() == HIDDEN)) {
|
||||
// If we can't get it from the cache, pretend its not present.
|
||||
// If all wasn't selected, and its HIDDEN, pretend its not present.
|
||||
if (e == null || (e.getProject().getState() == HIDDEN && !all && state != HIDDEN)) {
|
||||
// If we can't get it from the cache, pretend it's not present.
|
||||
// If all wasn't selected, and it's HIDDEN, pretend it's not present.
|
||||
// If state HIDDEN wasn't selected, and it's HIDDEN, pretend it's not present.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state != null && e.getProject().getState() != state) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@@ -191,37 +191,56 @@ public class ListProjectsIT extends AbstractDaemonTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listWithHiddenProject() throws Exception {
|
||||
public void listWithHiddenAndReadonlyProjects() throws Exception {
|
||||
Project.NameKey hidden = createProject("project-to-hide");
|
||||
Project.NameKey readonly = createProject("project-to-read");
|
||||
|
||||
// The project is included because it was not hidden yet
|
||||
// Set project read-only
|
||||
ConfigInput input = new ConfigInput();
|
||||
input.state = ProjectState.READ_ONLY;
|
||||
ConfigInfo info = gApi.projects().name(readonly.get()).config(input);
|
||||
assertThat(info.state).isEqualTo(input.state);
|
||||
|
||||
// The hidden project is included because it was not hidden yet.
|
||||
// The read-only project is included.
|
||||
assertThatNameList(gApi.projects().list().get())
|
||||
.containsExactly(allProjects, allUsers, project, hidden)
|
||||
.containsExactly(allProjects, allUsers, project, hidden, readonly)
|
||||
.inOrder();
|
||||
|
||||
// Hide the project
|
||||
ConfigInput input = new ConfigInput();
|
||||
input.state = ProjectState.HIDDEN;
|
||||
ConfigInfo info = gApi.projects().name(hidden.get()).config(input);
|
||||
info = gApi.projects().name(hidden.get()).config(input);
|
||||
assertThat(info.state).isEqualTo(input.state);
|
||||
|
||||
// Project is still accessible directly
|
||||
gApi.projects().name(hidden.get()).get();
|
||||
|
||||
// But is not included in the list
|
||||
// Hidden project is not included in the list
|
||||
assertThatNameList(gApi.projects().list().get())
|
||||
.containsExactly(allProjects, allUsers, project)
|
||||
.containsExactly(allProjects, allUsers, project, readonly)
|
||||
.inOrder();
|
||||
|
||||
// ALL filter applies to type, and doesn't include hidden state
|
||||
assertThatNameList(gApi.projects().list().withType(FilterType.ALL).get())
|
||||
.containsExactly(allProjects, allUsers, project)
|
||||
.containsExactly(allProjects, allUsers, project, readonly)
|
||||
.inOrder();
|
||||
|
||||
// "All" boolean option causes hidden projects to be included
|
||||
assertThatNameList(gApi.projects().list().withAll(true).get())
|
||||
.containsExactly(allProjects, allUsers, project, hidden)
|
||||
.containsExactly(allProjects, allUsers, project, hidden, readonly)
|
||||
.inOrder();
|
||||
|
||||
// "State" option causes only the projects in that state to be included
|
||||
assertThatNameList(gApi.projects().list().withState(ProjectState.HIDDEN).get())
|
||||
.containsExactly(hidden);
|
||||
assertThatNameList(gApi.projects().list().withState(ProjectState.READ_ONLY).get())
|
||||
.containsExactly(readonly);
|
||||
assertThatNameList(gApi.projects().list().withState(ProjectState.ACTIVE).get())
|
||||
.containsExactly(allProjects, allUsers, project)
|
||||
.inOrder();
|
||||
|
||||
// Cannot use "all" and "state" together
|
||||
assertBadRequest(gApi.projects().list().withAll(true).withState(ProjectState.ACTIVE));
|
||||
}
|
||||
|
||||
private void assertBadRequest(ListRequest req) throws Exception {
|
||||
|
Reference in New Issue
Block a user