diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index afe3d11dd..e430eb5ea 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -182,6 +182,10 @@ You can modify this table using [`pixi task`](cli.md#task). !!! note Specify different tasks for different platforms using the [target](#the-target-table) table +!!! info + If you want to hide a task from showing up with `pixi task list` or `pixi info`, you can prefix the name with `_`. + For example, if you want to hide `depending`, you can rename it to `_depending`. + ## The `system-requirements` table The system requirements are used to define minimal system specifications used during dependency resolution. diff --git a/src/cli/info.rs b/src/cli/info.rs index 83bfb32ef..d00266505 100644 --- a/src/cli/info.rs +++ b/src/cli/info.rs @@ -137,7 +137,17 @@ impl Display for EnvironmentInfo { )?; } if !self.tasks.is_empty() { - let tasks_list = self.tasks.iter().map(|t| t.fancy_display()).format(", "); + let tasks_list = self + .tasks + .iter() + .filter_map(|t| { + if !t.as_str().starts_with('_') { + Some(t.fancy_display()) + } else { + None + } + }) + .format(", "); writeln!(f, "{:>WIDTH$}: {}", bold.apply_to("Tasks"), tasks_list)?; } Ok(()) diff --git a/src/cli/run.rs b/src/cli/run.rs index cbf8a91e5..22eb70026 100644 --- a/src/cli/run.rs +++ b/src/cli/run.rs @@ -204,23 +204,13 @@ pub async fn execute(args: Args) -> miette::Result<()> { fn command_not_found<'p>(project: &'p Project, explicit_environment: Option>) { let available_tasks: HashSet = if let Some(explicit_environment) = explicit_environment { - explicit_environment - .tasks(Some(Platform::current())) - .into_iter() - .flat_map(|tasks| tasks.into_keys()) - .map(ToOwned::to_owned) - .collect() + explicit_environment.get_filtered_tasks() } else { project .environments() .into_iter() .filter(|env| verify_current_platform_has_required_virtual_packages(env).is_ok()) - .flat_map(|env| { - env.tasks(Some(Platform::current())) - .into_iter() - .flat_map(|tasks| tasks.into_keys()) - .map(ToOwned::to_owned) - }) + .flat_map(|env| env.get_filtered_tasks()) .collect() }; diff --git a/src/cli/task.rs b/src/cli/task.rs index 7c8ca495a..6e9ebc5ac 100644 --- a/src/cli/task.rs +++ b/src/cli/task.rs @@ -1,12 +1,16 @@ +use crate::project::manifest::EnvironmentName; use crate::project::manifest::FeatureName; +use crate::project::virtual_packages::verify_current_platform_has_required_virtual_packages; use crate::task::{quote, Alias, CmdArgs, Execute, Task, TaskName}; use crate::Project; use clap::Parser; use indexmap::IndexMap; use itertools::Itertools; use rattler_conda_types::Platform; +use std::collections::HashSet; use std::error::Error; use std::path::PathBuf; +use std::str::FromStr; use toml_edit::{Array, Item, Table, Value}; #[derive(Parser, Debug)] @@ -135,17 +139,22 @@ impl From for Task { Self::Plain(cmd_args) } else { let cwd = value.cwd; - let mut env = IndexMap::new(); - for (key, value) in value.env { - env.insert(key, value); - } + let env = if value.env.is_empty() { + None + } else { + let mut env = IndexMap::new(); + for (key, value) in value.env { + env.insert(key, value); + } + Some(env) + }; Self::Execute(Execute { cmd: CmdArgs::Single(cmd_args), depends_on, inputs: None, outputs: None, cwd, - env: Some(env), + env, }) } } @@ -273,15 +282,34 @@ pub fn execute(args: Args) -> miette::Result<()> { ); } Operation::List(args) => { - let environment = project.environment_from_name_or_env_var(args.environment)?; - let tasks = environment - .tasks(Some(Platform::current()))? - .into_keys() - .collect_vec(); - if tasks.is_empty() { + let explicit_environment = args + .environment + .map(|n| EnvironmentName::from_str(n.as_str())) + .transpose()? + .map(|n| { + project + .environment(&n) + .ok_or_else(|| miette::miette!("unknown environment '{n}'")) + }) + .transpose()?; + let available_tasks: HashSet = + if let Some(explicit_environment) = explicit_environment { + explicit_environment.get_filtered_tasks() + } else { + project + .environments() + .into_iter() + .filter(|env| { + verify_current_platform_has_required_virtual_packages(env).is_ok() + }) + .flat_map(|env| env.get_filtered_tasks()) + .collect() + }; + + if available_tasks.is_empty() { eprintln!("No tasks found",); } else { - let formatted: String = tasks + let formatted: String = available_tasks .iter() .sorted() .map(|name| { diff --git a/src/project/environment.rs b/src/project/environment.rs index f638e42ea..5c5597585 100644 --- a/src/project/environment.rs +++ b/src/project/environment.rs @@ -9,6 +9,7 @@ use crate::task::TaskName; use crate::{task::Task, Project}; use itertools::Either; use rattler_conda_types::Platform; +use std::collections::HashSet; use std::hash::{Hash, Hasher}; use std::{collections::HashMap, fmt::Debug}; @@ -116,6 +117,23 @@ impl<'p> Environment<'p> { Ok(result) } + /// Return all tasks available for the given environment + /// This will not return task prefixed with _ + pub fn get_filtered_tasks(&self) -> HashSet { + self.tasks(Some(Platform::current())) + .into_iter() + .flat_map(|tasks| { + tasks.into_iter().filter_map(|(key, _)| { + if !key.as_str().starts_with('_') { + Some(key) + } else { + None + } + }) + }) + .map(ToOwned::to_owned) + .collect() + } /// Returns the task with the given `name` and for the specified `platform` or an `UnknownTask` /// which explains why the task was not available. pub fn task( @@ -321,6 +339,28 @@ mod tests { .tasks(Some(Platform::Osx64)) .is_err()) } + #[test] + fn test_filtered_tasks() { + let manifest = Project::from_str( + Path::new("pixi.toml"), + r#" + [project] + name = "foobar" + channels = [] + platforms = ["linux-64", "osx-arm64", "osx-64", "win-64"] + + [tasks] + foo = "echo foo" + _bar = "echo bar" + "#, + ) + .unwrap(); + + let task = manifest.default_environment().get_filtered_tasks(); + + assert_eq!(task.len(), 1); + assert_eq!(task.contains(&"foo".into()), true); + } fn format_dependencies(dependencies: Dependencies) -> String { dependencies