Support searching changes that touch directories by regular expressions
Signed-off-by: Edwin Kempin <ekempin@google.com>
Change-Id: I8865dbf9b6dd7bd3b83f2227206f00c8690ddefb
diff --git a/Documentation/user-search.txt b/Documentation/user-search.txt
index 51dc38e..d596730 100644
--- a/Documentation/user-search.txt
+++ b/Documentation/user-search.txt
@@ -317,6 +317,10 @@
+
Slash ('/') is used path separator. Leading and trailing slashes are allowed
but are not mandatory.
++
+If 'DIR' starts with `^` it matches directories and directory segments by
+regular expression. The link:http://www.brics.dk/automaton/[dk.brics.automaton
+library] is used for evaluation of such patterns.
[[footer]]
footer:'FOOTER'::
diff --git a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
index 33e1575..b62a1d7 100644
--- a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
+++ b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -781,6 +781,10 @@
@Operator
public Predicate<ChangeData> directory(String directory) throws QueryParseException {
if (args.getSchema().hasField(ChangeField.DIRECTORY)) {
+ if (directory.startsWith("^")) {
+ return new RegexDirectoryPredicate(directory);
+ }
+
return new DirectoryPredicate(directory);
}
throw new QueryParseException("'directory' operator is not supported by change index version");
diff --git a/java/com/google/gerrit/server/query/change/RegexDirectoryPredicate.java b/java/com/google/gerrit/server/query/change/RegexDirectoryPredicate.java
new file mode 100644
index 0000000..1d49f1e
--- /dev/null
+++ b/java/com/google/gerrit/server/query/change/RegexDirectoryPredicate.java
@@ -0,0 +1,48 @@
+// Copyright (C) 2019 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.server.query.change;
+
+import com.google.gerrit.server.index.change.ChangeField;
+import com.google.gwtorm.server.OrmException;
+import dk.brics.automaton.RegExp;
+import dk.brics.automaton.RunAutomaton;
+
+public class RegexDirectoryPredicate extends ChangeRegexPredicate {
+ protected final RunAutomaton pattern;
+
+ public RegexDirectoryPredicate(String re) {
+ super(ChangeField.DIRECTORY, re);
+
+ if (re.startsWith("^")) {
+ re = re.substring(1);
+ }
+
+ if (re.endsWith("$") && !re.endsWith("\\$")) {
+ re = re.substring(0, re.length() - 1);
+ }
+
+ this.pattern = new RunAutomaton(new RegExp(re).toAutomaton());
+ }
+
+ @Override
+ public boolean match(ChangeData cd) throws OrmException {
+ return ChangeField.getDirectories(cd).stream().anyMatch(pattern::run);
+ }
+
+ @Override
+ public int getCost() {
+ return 1;
+ }
+}
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index 06deb9d..7872a82 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -1581,6 +1581,11 @@
assertQuery("directory:/b/c", change5);
assertQuery("directory:/b/c/", change5);
assertQuery("directory:b/c/", change5);
+
+ // match by regexp
+ assertQuery("directory:^.*va.*", change2);
+ assertQuery("directory:^documentation/.*/slides", change3);
+ assertQuery("directory:^train.*", change3);
}
@Test