Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Show all available task with task list #1286

Merged
merged 26 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from 25 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
4 changes: 4 additions & 0 deletions docs/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
12 changes: 11 additions & 1 deletion src/cli/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
Expand Down
14 changes: 2 additions & 12 deletions src/cli/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,23 +204,13 @@ pub async fn execute(args: Args) -> miette::Result<()> {
fn command_not_found<'p>(project: &'p Project, explicit_environment: Option<Environment<'p>>) {
let available_tasks: HashSet<TaskName> =
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()
};

Expand Down
52 changes: 40 additions & 12 deletions src/cli/task.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down Expand Up @@ -135,17 +139,22 @@ impl From<AddArgs> 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,
})
}
}
Expand Down Expand Up @@ -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<TaskName> =
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| {
Expand Down
40 changes: 40 additions & 0 deletions src/project/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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<TaskName> {
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(
Expand Down Expand Up @@ -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"]
hoxbro marked this conversation as resolved.
Show resolved Hide resolved

[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
Expand Down
Loading