Skip to content

Commit

Permalink
fix(task): properly handle task name wildcards with --recursive (#27396)
Browse files Browse the repository at this point in the history
This commit fixes `deno task` by checking if the provided
task name actually has a wildcard char ("*").

Previously, if the "--recursive" flag was passed, the task name
was treated as a regex, which lead to a situation where exact task
name resulted in a regex that matched all tasks with the specific
prefix.

This commit fixes it, by checking if the provided task name, is an exact
name, or is it a wildcard match.

Closes #27370
Closes #27401
Closes #27408
  • Loading branch information
bartlomieju authored Dec 18, 2024
1 parent 9d7174e commit 14e4064
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 2 deletions.
50 changes: 48 additions & 2 deletions cli/tools/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub async fn execute_script(
return Ok(0);
};

let task_regex = arg_to_regex(task_name)?;
let task_name_filter = arg_to_task_name_filter(task_name)?;
let mut packages_task_info: Vec<PackageTaskInfo> = vec![];

for folder in workspace.config_folders() {
Expand Down Expand Up @@ -137,12 +137,20 @@ pub async fn execute_script(

// Match tasks in deno.json
for name in tasks_config.task_names() {
if task_regex.is_match(name) && !visited.contains(name) {
let matches_filter = match &task_name_filter {
TaskNameFilter::Exact(n) => *n == name,
TaskNameFilter::Regex(re) => re.is_match(name),
};
if matches_filter && !visited.contains(name) {
matched.insert(name.to_string());
visit_task(&tasks_config, &mut visited, name);
}
}

if matched.is_empty() {
continue;
}

packages_task_info.push(PackageTaskInfo {
matched_tasks: matched
.iter()
Expand Down Expand Up @@ -902,3 +910,41 @@ fn strip_ansi_codes_and_escape_control_chars(s: &str) -> String {
})
.collect()
}

fn arg_to_task_name_filter(input: &str) -> Result<TaskNameFilter, AnyError> {
if !input.contains("*") {
return Ok(TaskNameFilter::Exact(input));
}

let mut regex_str = regex::escape(input);
regex_str = regex_str.replace("\\*", ".*");
let re = Regex::new(&regex_str)?;
Ok(TaskNameFilter::Regex(re))
}

#[derive(Debug)]
enum TaskNameFilter<'s> {
Exact(&'s str),
Regex(regex::Regex),
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_arg_to_task_name_filter() {
assert!(matches!(
arg_to_task_name_filter("test").unwrap(),
TaskNameFilter::Exact("test")
));
assert!(matches!(
arg_to_task_name_filter("test-").unwrap(),
TaskNameFilter::Exact("test-")
));
assert!(matches!(
arg_to_task_name_filter("test*").unwrap(),
TaskNameFilter::Regex(_)
));
}
}
11 changes: 11 additions & 0 deletions tests/specs/task/workspace_regex_match/__test__.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"tempDir": true,
"tests": {
// Regression test for https://github.com/denoland/deno/issues/27370
"root": {
"args": "task test-all",
"output": "root.out",
"exitCode": 0
}
}
}
6 changes: 6 additions & 0 deletions tests/specs/task/workspace_regex_match/deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"workspace": ["./subdir"],
"tasks": {
"test-all": "deno task --recursive test"
}
}
3 changes: 3 additions & 0 deletions tests/specs/task/workspace_regex_match/root.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Task test-all deno task --recursive test
Task test echo 'ok'
ok
5 changes: 5 additions & 0 deletions tests/specs/task/workspace_regex_match/subdir/deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"tasks": {
"test": "echo 'ok'"
}
}

0 comments on commit 14e4064

Please sign in to comment.