Add optional chainable subtask support
Use the "|" character to indicate that it is valid for a subtask to not
exist. Follow the "|" with the name of an alternate subtask if desired.
Change-Id: Idff6d5142def0208305fad616a0b6c5db690baba
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
index 1d7b9d5..b1fe1a1 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskTree.java
@@ -36,6 +36,8 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.eclipse.jgit.errors.ConfigInvalidException;
/**
@@ -46,6 +48,8 @@
*/
public class TaskTree {
protected static final String TASK_DIR = "task";
+ protected static final Pattern OPTIONAL_TASK_PATTERN =
+ Pattern.compile("([^ |]*( *[^ |])*) *\\| *");
protected final AccountResolver accountResolver;
protected final AllUsersNameProvider allUsers;
@@ -166,11 +170,28 @@
protected List<Task> getSubTasks() {
List<Task> tasks = new ArrayList<>();
for (String subTask : definition.subTasks) {
- tasks.add(definition.config.getTask(subTask));
+ addSubTaskTo(subTask, tasks);
}
return tasks;
}
+ protected void addSubTaskTo(String subTaskEntry, List<Task> tasks) {
+ int end = 0;
+ Matcher m = OPTIONAL_TASK_PATTERN.matcher(subTaskEntry);
+ while (m.find()) {
+ end = m.end();
+ Task subTask = definition.config.getTask(m.group(1));
+ if (subTask != null) {
+ tasks.add(subTask);
+ return;
+ }
+ }
+ String last = subTaskEntry.substring(end);
+ if (!"".equals(last)) { // Last entry was not optional
+ tasks.add(definition.config.getTask(subTaskEntry.substring(end)));
+ }
+ }
+
protected List<Task> getTasks(External external)
throws ConfigInvalidException, IOException, OrmException {
return getTasks(resolveUserBranch(external.user), external.file);
diff --git a/src/main/resources/Documentation/task.md b/src/main/resources/Documentation/task.md
index 6c11074..326c550 100644
--- a/src/main/resources/Documentation/task.md
+++ b/src/main/resources/Documentation/task.md
@@ -172,6 +172,29 @@
```
subtask = "Code Review"
subtask = "License Approval"
+ ...
+ [task "Code Review"]
+ ...
+ [task "License Approval"]
+ ...
+```
+
+To define a subtask that may not exist and that will not cause the parent task
+to be INVALID, follow the subtask name with pipe (`|`) character. This feature
+is particularly useful when a property is used in the subtask name.
+
+```
+ subtask = Optional Subtask {$_name} |
+```
+
+To define an alternate subtask to load when an optional subtask does not exist,
+list the alterante subtask name after the pipe (`|`) character. This feature
+may be chained together as many times as needed.
+
+```
+ subtask = Optional Subtask {$_name} |
+ Backup Optional Subtask {$_name} Backup |
+ Default Subtask # Must exist if the above two don't!
```
`subtasks-external`
diff --git a/src/main/resources/Documentation/task_states.md b/src/main/resources/Documentation/task_states.md
index 33794e5..5f41202 100644
--- a/src/main/resources/Documentation/task_states.md
+++ b/src/main/resources/Documentation/task_states.md
@@ -77,6 +77,10 @@
in-progress = NOT is:open
pass = NOT is:open
+[root "Root Optional subtasks"]
+ subtask = OPTIONAL MISSING |
+ subtask = Subtask Optional |
+
[root "Subtasks File"]
subtasks-file = common.config
@@ -143,6 +147,12 @@
applicable = is:open
pass = is:open
+[task "Subtask Optional"]
+ subtask = Subtask PASS |
+ subtask = OPTIONAL MISSING | Subtask FAIL
+ subtask = OPTIONAL MISSING | OPTIONAL MISSING |
+ subtask = OPTIONAL MISSING | OPTIONAL MISSING | Subtask READY
+
[task "Subtask NA"]
applicable = NOT is:open # Assumes test query is "is:open"
@@ -264,6 +274,9 @@
[task "Subtask INVALID"]
fail-hint = Use when an INVALID subtask is needed, not meant as a test case in itself
+[task "Subtask Optional"]
+ subtask = MISSING | MISSING
+
[task "NA Bad PASS query"]
applicable = NOT is:open # Assumes test query is "is:open"
fail = True
@@ -454,6 +467,42 @@
},
{
"hasPass" : false,
+ "name" : "Root Optional subtasks",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "hasPass" : true,
+ "name" : "Subtask PASS",
+ "status" : "PASS"
+ },
+ {
+ "hasPass" : true,
+ "name" : "Subtask FAIL",
+ "status" : "FAIL"
+ },
+ {
+ "hasPass" : true,
+ "name" : "Subtask READY",
+ "status" : "READY",
+ "subTasks" : [
+ {
+ "hasPass" : true,
+ "name" : "Subtask PASS",
+ "status" : "PASS"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "hasPass" : false,
"name" : "Subtasks File",
"status" : "WAITING",
"subTasks" : [
@@ -747,6 +796,17 @@
},
{
"hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "hasPass" : false,
"name" : "Looping",
"status" : "WAITING",
"subTasks" : [
diff --git a/test/all b/test/all
index a993e95..c99aa48 100644
--- a/test/all
+++ b/test/all
@@ -190,6 +190,48 @@
{
"applicable" : true,
"hasPass" : false,
+ "name" : "Root Optional subtasks",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask PASS",
+ "status" : "PASS"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask FAIL",
+ "status" : "FAIL"
+ },
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask READY",
+ "status" : "READY",
+ "subTasks" : [
+ {
+ "applicable" : true,
+ "hasPass" : true,
+ "name" : "Subtask PASS",
+ "status" : "PASS"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "applicable" : true,
+ "hasPass" : false,
"name" : "Subtasks File",
"status" : "WAITING",
"subTasks" : [
@@ -527,6 +569,18 @@
"status" : "INVALID"
},
{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
"applicable" : false,
"hasPass" : true,
"name" : "NA Bad PASS query",
@@ -663,6 +717,18 @@
"status" : "INVALID"
},
{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
"applicable" : false,
"hasPass" : true,
"name" : "NA Bad PASS query",
diff --git a/test/invalid b/test/invalid
index 27df0ec..840c3da 100644
--- a/test/invalid
+++ b/test/invalid
@@ -135,6 +135,18 @@
"status" : "INVALID"
},
{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
"applicable" : false,
"hasPass" : true,
"name" : "NA Bad PASS query",
@@ -259,6 +271,18 @@
"status" : "INVALID"
},
{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
"applicable" : false,
"hasPass" : true,
"name" : "NA Bad PASS query",
diff --git a/test/invalid-applicable b/test/invalid-applicable
index 514fca9..8e52fa0 100644
--- a/test/invalid-applicable
+++ b/test/invalid-applicable
@@ -103,6 +103,17 @@
},
{
"hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
+ "hasPass" : false,
"name" : "Looping",
"status" : "WAITING",
"subTasks" : [
diff --git a/test/preview b/test/preview
index 60ba53f..e2706ea 100644
--- a/test/preview
+++ b/test/preview
@@ -91,6 +91,18 @@
"status" : "INVALID"
},
{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
"applicable" : false,
"hasPass" : true,
"name" : "NA Bad PASS query",
@@ -262,6 +274,18 @@
"status" : "INVALID"
},
{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
"applicable" : false,
"hasPass" : true,
"name" : "NA Bad PASS query",
diff --git a/test/preview.invalid b/test/preview.invalid
index be1bb7f..86d12f1 100644
--- a/test/preview.invalid
+++ b/test/preview.invalid
@@ -91,6 +91,18 @@
"status" : "INVALID"
},
{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
"applicable" : false,
"hasPass" : true,
"name" : "NA Bad PASS query",
@@ -215,6 +227,18 @@
"status" : "INVALID"
},
{
+ "applicable" : true,
+ "hasPass" : false,
+ "name" : "Subtask Optional",
+ "status" : "WAITING",
+ "subTasks" : [
+ {
+ "name" : "UNKNOWN",
+ "status" : "INVALID"
+ }
+ ]
+ },
+ {
"applicable" : false,
"hasPass" : true,
"name" : "NA Bad PASS query",