Support to list child projects recursively via REST

Change-Id: I046e4d546ca1f0a971382816de4ea76aef035f3f
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
This commit is contained in:
Edwin Kempin
2013-03-19 11:10:57 +01:00
committed by Gerrit Code Review
parent 5b6c406e38
commit f95bd17c34
4 changed files with 138 additions and 3 deletions

View File

@@ -535,6 +535,63 @@ returned that describe the child projects.
]
----
To resolve the child projects of a project recursively the parameter
`recursive` can be set.
Child projects that are not visible to the calling user are ignored and
are not resolved further.
.Request
----
GET /projects/Public-Projects/children/?recursive HTTP/1.0
----
.Response
----
HTTP/1.1 200 OK
Content-Disposition: attachment
Content-Type: application/json;charset=UTF-8
)]}'
[
{
"kind": "gerritcodereview#project",
"id": "gerrit",
"name": "gerrit",
"parent": "Public-Projects",
"description": "Gerrit Code Review"
},
{
"kind": "gerritcodereview#project",
"id": "plugins%2Freplication",
"name": "plugins/replication",
"parent": "Public-Plugins",
"description": "Copies to other servers using the Git protocol"
},
{
"kind": "gerritcodereview#project",
"id": "plugins%2Freviewnotes",
"name": "plugins/reviewnotes",
"parent": "Public-Plugins",
"description": "Annotates merged commits using notes on refs/notes/review."
},
{
"kind": "gerritcodereview#project",
"id": "plugins%2Fsingleusergroup",
"name": "plugins/singleusergroup",
"parent": "Public-Plugins",
"description": "GroupBackend enabling users to be directly added to access rules"
},
{
"kind": "gerritcodereview#project",
"id": "Public-Plugins",
"name": "Public-Plugins",
"parent": "Public-Projects",
"description": "Parent project for plugins/*"
}
]
----
[[get-child-project]]
Get Child Project
~~~~~~~~~~~~~~~~~

View File

@@ -93,6 +93,29 @@ public class ListChildProjectsIT extends AbstractDaemonTest {
assertProjects(Arrays.asList(child1, child2), children);
}
@Test
public void listChildrenRecursively() throws IOException, JSchException {
SshSession sshSession = new SshSession(admin);
Project.NameKey child1 = new Project.NameKey("p1");
createProject(sshSession, child1.get());
createProject(sshSession, "p2");
Project.NameKey child1_1 = new Project.NameKey("p1.1");
createProject(sshSession, child1_1.get(), child1);
Project.NameKey child1_2 = new Project.NameKey("p1.2");
createProject(sshSession, child1_2.get(), child1);
Project.NameKey child1_1_1 = new Project.NameKey("p1.1.1");
createProject(sshSession, child1_1_1.get(), child1_1);
Project.NameKey child1_1_1_1 = new Project.NameKey("p1.1.1.1");
createProject(sshSession, child1_1_1_1.get(), child1_1_1);
RestResponse r = GET("/projects/" + child1.get() + "/children/?recursive");
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
List<ProjectInfo> children =
(new Gson()).fromJson(r.getReader(),
new TypeToken<List<ProjectInfo>>() {}.getType());
assertProjects(Arrays.asList(child1_1, child1_2, child1_1_1, child1_1_1_1), children);
}
private RestResponse GET(String endpoint) throws IOException {
return session.get(endpoint);
}

View File

@@ -15,30 +15,49 @@
package com.google.gerrit.server.project;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.project.ProjectJson.ProjectInfo;
import com.google.inject.Inject;
import org.kohsuke.args4j.Option;
import java.util.List;
import java.util.Map;
public class ListChildProjects implements RestReadView<ProjectResource> {
@Option(name = "--recursive", usage = "to list child projects recursively")
private boolean recursive;
private final ProjectCache projectCache;
private final AllProjectsName allProjects;
private final ProjectJson json;
private final ProjectNode.Factory projectNodeFactory;
@Inject
ListChildProjects(ProjectCache projectCache, AllProjectsName allProjects,
ProjectJson json) {
ProjectJson json, ProjectNode.Factory projectNodeFactory) {
this.projectCache = projectCache;
this.allProjects = allProjects;
this.json = json;
this.projectNodeFactory = projectNodeFactory;
}
@Override
public List<ProjectInfo> apply(ProjectResource rsrc) {
if (recursive) {
return getChildProjectsRecursively(rsrc.getNameKey(),
rsrc.getControl().getCurrentUser());
} else {
return getDirectChildProjects(rsrc.getNameKey());
}
}
private List<ProjectInfo> getDirectChildProjects(Project.NameKey parent) {
List<ProjectInfo> childProjects = Lists.newArrayList();
for (Project.NameKey projectName : projectCache.all()) {
ProjectState e = projectCache.get(projectName);
@@ -46,10 +65,42 @@ public class ListChildProjects implements RestReadView<ProjectResource> {
// If we can't get it from the cache, pretend it's not present.
continue;
}
if (rsrc.getNameKey().equals(e.getProject().getParent(allProjects))) {
if (parent.equals(e.getProject().getParent(allProjects))) {
childProjects.add(json.format(e.getProject()));
}
}
return childProjects;
}
private List<ProjectInfo> getChildProjectsRecursively(Project.NameKey parent,
CurrentUser user) {
Map<Project.NameKey, ProjectNode> projects = Maps.newHashMap();
for (Project.NameKey name : projectCache.all()) {
ProjectState p = projectCache.get(name);
if (p == null) {
// If we can't get it from the cache, pretend it's not present.
continue;
}
projects.put(name, projectNodeFactory.create(p.getProject(),
p.controlFor(user).isVisible()));
}
for (ProjectNode key : projects.values()) {
ProjectNode node = projects.get(key.getParentName());
if (node != null) {
node.addChild(key);
}
}
return getChildProjectsRecursively(projects.get(parent));
}
private List<ProjectInfo> getChildProjectsRecursively(ProjectNode p) {
List<ProjectInfo> allChildren = Lists.newArrayList();
for (ProjectNode c : p.getChildren()) {
if (c.isVisible()) {
allChildren.add(json.format(c.getProject()));
allChildren.addAll(getChildProjectsRecursively(c));
}
}
return allChildren;
}
}

View File

@@ -57,6 +57,10 @@ public class ProjectNode implements TreeNode, Comparable<ProjectNode> {
return allProjectsName.equals(project.getNameKey());
}
public Project getProject() {
return project;
}
@Override
public String getDisplayName() {
return project.getName();
@@ -68,7 +72,7 @@ public class ProjectNode implements TreeNode, Comparable<ProjectNode> {
}
@Override
public SortedSet<? extends TreeNode> getChildren() {
public SortedSet<? extends ProjectNode> getChildren() {
return children;
}