Add support for regex in project list screen
Add support for regex in project list screen filter. If filter start with '^', then the filter will be interpreted as a regex. Feature: Issue 2751 Change-Id: I1cf8a0f9fc18a6e286a2a26c71be77f1d4f16741
This commit is contained in:
parent
91b7f7ce39
commit
b8aae411a8
@ -175,6 +175,38 @@ List all projects that start with `platform/`:
|
||||
+
|
||||
E.g. this feature can be used by suggestion client UI's to limit results.
|
||||
|
||||
Regex(r)::
|
||||
Limit the results to those projects that match the specified regex.
|
||||
+
|
||||
Boundary matchers '^' and '$' are implicit. For example: the regex 'test.*' will
|
||||
match any projects that start with 'test' and regex '.*test' will match any
|
||||
project that end with 'test'.
|
||||
+
|
||||
List all projects that match regex `test.*project`:
|
||||
+
|
||||
.Request
|
||||
----
|
||||
GET /projects/?r=test.*project 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",
|
||||
},
|
||||
"test/some-other-project": {
|
||||
"id": "test%2Fsome-other-project",
|
||||
}
|
||||
}
|
||||
|
||||
----
|
||||
|
||||
Skip(S)::
|
||||
Skip the given number of projects from the beginning of the list.
|
||||
+
|
||||
|
@ -128,6 +128,31 @@ public class ListProjectsIT extends AbstractDaemonTest {
|
||||
result.values());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listProjectsWithRegex() 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/?r=.*some");
|
||||
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||
Map<String, ProjectInfo> result = toProjectInfoMap(r);
|
||||
assertProjects(Arrays.asList(projectAwesome), result.values());
|
||||
|
||||
r = GET("/projects/?r=[.*some");
|
||||
assertEquals(HttpStatus.SC_BAD_REQUEST, r.getStatusCode());
|
||||
|
||||
r = GET("/projects/?r=.*");
|
||||
assertEquals(HttpStatus.SC_OK, r.getStatusCode());
|
||||
result = toProjectInfoMap(r);
|
||||
assertProjects(Arrays.asList(someProject, someOtherProject, projectAwesome,
|
||||
project, allUsers), result.values());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listProjectsWithSkip() throws IOException, JSchException {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
|
@ -56,7 +56,11 @@ public class ProjectMap extends NativeMap<ProjectInfo> {
|
||||
public static void match(String match, int limit, int start, AsyncCallback<ProjectMap> cb) {
|
||||
RestApi call = new RestApi("/projects/");
|
||||
if (match != null) {
|
||||
call.addParameter("m", match);
|
||||
if (match.startsWith("^")) {
|
||||
call.addParameter("r", match);
|
||||
} else {
|
||||
call.addParameter("m", match);
|
||||
}
|
||||
}
|
||||
if (limit > 0) {
|
||||
call.addParameter("n", limit);
|
||||
|
@ -23,6 +23,7 @@ import com.google.gerrit.common.data.GroupReference;
|
||||
import com.google.gerrit.common.errors.NoSuchGroupException;
|
||||
import com.google.gerrit.extensions.common.ProjectInfo;
|
||||
import com.google.gerrit.extensions.common.WebLinkInfo;
|
||||
import com.google.gerrit.extensions.restapi.BadRequestException;
|
||||
import com.google.gerrit.extensions.restapi.BinaryResult;
|
||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||
import com.google.gerrit.extensions.restapi.TopLevelResource;
|
||||
@ -42,6 +43,9 @@ import com.google.gson.reflect.TypeToken;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import dk.brics.automaton.RegExp;
|
||||
import dk.brics.automaton.RunAutomaton;
|
||||
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
@ -163,6 +167,11 @@ public class ListProjects implements RestReadView<TopLevelResource> {
|
||||
this.matchSubstring = matchSubstring;
|
||||
}
|
||||
|
||||
@Option(name = "-r", metaVar = "REGEX", usage = "match project regex")
|
||||
public void setMatchRegex(String matchRegex) {
|
||||
this.matchRegex = matchRegex;
|
||||
}
|
||||
|
||||
@Option(name = "--has-acl-for", metaVar = "GROUP", usage =
|
||||
"displays only projects on which access rights for this group are directly assigned")
|
||||
public void setGroupUuid(AccountGroup.UUID groupUuid) {
|
||||
@ -178,6 +187,7 @@ public class ListProjects implements RestReadView<TopLevelResource> {
|
||||
private int start;
|
||||
private String matchPrefix;
|
||||
private String matchSubstring;
|
||||
private String matchRegex;
|
||||
private AccountGroup.UUID groupUuid;
|
||||
|
||||
@Inject
|
||||
@ -216,7 +226,7 @@ public class ListProjects implements RestReadView<TopLevelResource> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object apply(TopLevelResource resource) {
|
||||
public Object apply(TopLevelResource resource) throws BadRequestException {
|
||||
if (format == OutputFormat.TEXT) {
|
||||
ByteArrayOutputStream buf = new ByteArrayOutputStream();
|
||||
display(buf);
|
||||
@ -227,12 +237,13 @@ public class ListProjects implements RestReadView<TopLevelResource> {
|
||||
return apply();
|
||||
}
|
||||
|
||||
public Map<String, ProjectInfo> apply() {
|
||||
public Map<String, ProjectInfo> apply() throws BadRequestException {
|
||||
format = OutputFormat.JSON;
|
||||
return display(null);
|
||||
}
|
||||
|
||||
public Map<String, ProjectInfo> display(OutputStream displayOutputStream) {
|
||||
public Map<String, ProjectInfo> display(OutputStream displayOutputStream)
|
||||
throws BadRequestException {
|
||||
PrintWriter stdout = null;
|
||||
if (displayOutputStream != null) {
|
||||
try {
|
||||
@ -436,7 +447,7 @@ public class ListProjects implements RestReadView<TopLevelResource> {
|
||||
}
|
||||
}
|
||||
|
||||
private Iterable<Project.NameKey> scan() {
|
||||
private Iterable<Project.NameKey> scan() throws BadRequestException {
|
||||
if (matchPrefix != null) {
|
||||
return projectCache.byName(matchPrefix);
|
||||
} else if (matchSubstring != null) {
|
||||
@ -447,6 +458,28 @@ public class ListProjects implements RestReadView<TopLevelResource> {
|
||||
.contains(matchSubstring.toLowerCase(Locale.US));
|
||||
}
|
||||
});
|
||||
} else if (matchRegex != null) {
|
||||
if (matchRegex.startsWith("^")) {
|
||||
matchRegex = matchRegex.substring(1);
|
||||
if (matchRegex.endsWith("$") && !matchRegex.endsWith("\\$")) {
|
||||
matchRegex = matchRegex.substring(0, matchRegex.length() - 1);
|
||||
}
|
||||
}
|
||||
if (matchRegex.equals(".*")) {
|
||||
return projectCache.all();
|
||||
}
|
||||
try {
|
||||
final RunAutomaton a =
|
||||
new RunAutomaton(new RegExp(matchRegex).toAutomaton());
|
||||
return Iterables.filter(projectCache.all(),
|
||||
new Predicate<Project.NameKey>() {
|
||||
public boolean apply(Project.NameKey in) {
|
||||
return a.run(in.get());
|
||||
}
|
||||
});
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new BadRequestException(e.getMessage());
|
||||
}
|
||||
} else {
|
||||
return projectCache.all();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user