ListProjects: Allow to filter list by project state

Bug: Issue 7747
Change-Id: Ibf39b408fce8e76a61706ae45da433faaf0391f2
This commit is contained in:
David Pursehouse
2017-11-28 13:37:48 +09:00
parent 1b1bb97571
commit 54508764eb
5 changed files with 88 additions and 13 deletions

View File

@@ -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
--

View File

@@ -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;
}
}
/**

View File

@@ -131,6 +131,8 @@ class ProjectsImpl implements Projects {
lp.setAll(request.isAll());
lp.setState(request.getState());
return lp.apply();
}

View File

@@ -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;
}

View File

@@ -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 {