Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion e2e/tasks/test_task_double_dash_behavior
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ EOF

# Usage spec handles its own flags (parsed by usage spec, not passed as $@)
# shellcheck disable=SC2016
assert "mise run with_usage -x myfile 2>&1" '[with_usage -x myfile] $ echo "custom=$usage_custom file=$usage_file args=$@"
assert "mise run with_usage -x myfile 2>&1" '[with_usage] $ echo "custom=$usage_custom file=$usage_file args=$@"
custom=true file=myfile args='

# But mise flags still go to mise (myfile is consumed by usage spec, not passed to $@)
Expand Down
29 changes: 29 additions & 0 deletions e2e/tasks/test_task_prefix_args_disambiguation
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash

# Test that task output prefixes include args only when the same task runs
# multiple times with different arguments (disambiguation), and omit args
# when there's no conflict.

cat <<'EOF' >mise.toml
[tasks.greet]
run = 'echo "hello $1"'

[tasks.build]
run = 'echo "building"'
EOF

# When the same task runs twice with different args, prefixes should include args
output="$(mise run greet alice ::: greet bob 2>&1)"
assert_contains "echo \"$output\"" "[greet alice]"
assert_contains "echo \"$output\"" "[greet bob]"

# When a task runs only once, prefix should NOT include args
output="$(mise run greet alice 2>&1)"
assert_not_contains "echo \"$output\"" "[greet alice]"
assert_contains "echo \"$output\"" "[greet]"

# Different tasks should not trigger disambiguation
output="$(mise run greet alice ::: build 2>&1)"
assert_not_contains "echo \"$output\"" "[greet alice]"
assert_contains "echo \"$output\"" "[greet]"
assert_contains "echo \"$output\"" "[build]"
3 changes: 2 additions & 1 deletion src/cli/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,8 @@ impl Run {
async fn prepare_tasks(&mut self, config: &Arc<Config>, mut tasks: Vec<Task>) -> Result<Deps> {
let fetcher = crate::task::task_fetcher::TaskFetcher::new(self.no_cache);
fetcher.fetch_tasks(&mut tasks).await?;
let tasks = Deps::new(config, tasks).await?;
let mut tasks = Deps::new(config, tasks).await?;
tasks.mark_ambiguous_prefixes();
self.is_linear = tasks.is_linear();
Ok(tasks)
}
Expand Down
20 changes: 20 additions & 0 deletions src/task/deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ impl Deps {
for idx in to_remove {
deps.graph.remove_node(idx);
}
deps.mark_ambiguous_prefixes();
Ok(deps)
}

Expand Down Expand Up @@ -228,6 +229,25 @@ impl Deps {
self.graph.node_indices().map(|idx| &self.graph[idx])
}

/// Mark tasks that share a display_name so their prefix includes args
/// for disambiguation (e.g. `[test-docker 4.1]` vs `[test-docker 4.2]`).
pub fn mark_ambiguous_prefixes(&mut self) {
let mut name_to_indices: HashMap<String, Vec<petgraph::graph::NodeIndex>> = HashMap::new();
for idx in self.graph.node_indices() {
name_to_indices
.entry(self.graph[idx].display_name.clone())
.or_default()
.push(idx);
}
for indices in name_to_indices.values() {
if indices.len() > 1 {
for &idx in indices {
self.graph[idx].show_args_in_prefix = true;
}
}
}
}

pub fn is_linear(&self) -> bool {
let mut graph = self.graph.clone();
// pop dependencies off, if we get multiple dependencies at once it's not linear
Expand Down
16 changes: 13 additions & 3 deletions src/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,11 @@ pub struct Task {
/// Name of the task template to extend (requires experimental = true)
#[serde(default)]
pub extends: Option<String>,

/// When true, include args in the output prefix to disambiguate tasks
/// with the same display_name but different arguments.
#[serde(skip)]
pub show_args_in_prefix: bool,
}

impl Task {
Expand Down Expand Up @@ -517,9 +522,13 @@ impl Task {

pub fn prefix(&self) -> String {
let max_width = 40;
let inner = format!("{} {}", self.display_name, self.args.join(" "));
let inner = inner.trim();
format!("[{}]", console::truncate_str(inner, max_width, "…"))
let inner = if self.show_args_in_prefix && !self.args.is_empty() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The maximum width for the prefix is hardcoded as 40. It would be better to define this as a constant to improve readability and maintainability, for example const MAX_PREFIX_WIDTH: usize = 40; at a module or impl level.

let s = format!("{} {}", self.display_name, self.args.join(" "));
s.trim().to_string()
} else {
self.display_name.clone()
};
format!("[{}]", console::truncate_str(&inner, max_width, "…"))
}

pub fn run(&self) -> &Vec<RunEntry> {
Expand Down Expand Up @@ -1267,6 +1276,7 @@ impl Default for Task {
timeout: None,
remote_file_source: None,
extends: None,
show_args_in_prefix: false,
}
}
}
Expand Down
Loading