Skip to content

Commit

Permalink
Remove dependency from feature through cli (#680)
Browse files Browse the repository at this point in the history
This adds `--feature FEATURENAME` to the `pixi remove` command. 

Did this one first as it is probably one of the simplest commands to
modify. To prepare for the full multi env integration.
  • Loading branch information
ruben-arts authored Jan 18, 2024
1 parent 2261787 commit 6746b43
Show file tree
Hide file tree
Showing 21 changed files with 514 additions and 76 deletions.
26 changes: 26 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,32 @@ pixi run task argument1 argument2
Checkout their [documentation](https://deno.land/[email protected]/tools/task_runner#task-runner) for the syntax and available commands.
This is done so that the run commands can be run across all platforms.

## `remove`

Removes dependencies from the `pixi.toml`.

##### Options

- `--manifest-path`: the path to `pixi.toml`, by default it searches for one in the parent directories.
- `--host`: Specifies a host dependency, important for building a package.
- `--build`: Specifies a build dependency, important for building a package.
- `--pypi`: Specifies a PyPI dependency, not a conda package.
- `--platform (-p)`: The platform from which the dependency should be removed.
- `--feature (-f)`: The feature from which the dependency should be removed.

```shell
pixi remove numpy
pixi remove numpy pandas pytorch
pixi remove --manifest-path ~/myproject/pixi.toml numpy
pixi remove --host python
pixi remove --build cmake
pixi remove --pypi requests
pixi remove --platform osx-64 --build clang
pixi remove --feature featurex clang
pixi remove --feature featurex --platform osx-64 clang
pixi remove --feature featurex --platform osx-64 --build clang
```

## `task`

If you want to make a shorthand for a specific command you can add a task for it.
Expand Down
22 changes: 16 additions & 6 deletions src/cli/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use miette::miette;
use rattler_conda_types::Platform;

use crate::environment::LockFileUsage;
use crate::project::manifest::FeatureName;
use crate::{consts, environment::get_up_to_date_prefix, project::SpecType, Project};

/// Remove the dependency from the project
Expand Down Expand Up @@ -34,6 +35,10 @@ pub struct Args {
/// The platform for which the dependency should be removed
#[arg(long, short)]
pub platform: Option<Platform>,

/// The feature for which the dependency should be removed
#[arg(long)]
pub feature: Option<String>,
}

fn convert_pkg_name<T>(deps: &[String]) -> miette::Result<Vec<T>>
Expand Down Expand Up @@ -69,6 +74,9 @@ pub async fn execute(args: Args) -> miette::Result<()> {
} else {
section_name
};
let feature_name = args
.feature
.map_or(FeatureName::Default, FeatureName::Named);

fn format_ok_message(pkg_name: &str, pkg_extras: &str, table_name: &str) -> String {
format!(
Expand All @@ -81,9 +89,10 @@ pub async fn execute(args: Args) -> miette::Result<()> {
if args.pypi {
let all_pkg_name = convert_pkg_name::<rip::types::PackageName>(&deps)?;
for dep in all_pkg_name.iter() {
let (name, req) = project
.manifest
.remove_pypi_dependency(dep, args.platform)?;
let (name, req) =
project
.manifest
.remove_pypi_dependency(dep, args.platform, &feature_name)?;
sucessful_output.push(format_ok_message(
name.as_str(),
&req.to_string(),
Expand All @@ -93,9 +102,10 @@ pub async fn execute(args: Args) -> miette::Result<()> {
} else {
let all_pkg_name = convert_pkg_name::<rattler_conda_types::PackageName>(&deps)?;
for dep in all_pkg_name.iter() {
let (name, req) = project
.manifest
.remove_dependency(dep, spec_type, args.platform)?;
let (name, req) =
project
.manifest
.remove_dependency(dep, spec_type, args.platform, &feature_name)?;
sucessful_output.push(format_ok_message(
name.as_source(),
&req.to_string(),
Expand Down
1 change: 1 addition & 0 deletions src/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ fn create_prefix_location_file(prefix_file: &Path) -> miette::Result<()> {
/// Runs the following checks to make sure the project is in a sane state:
/// 1. It verifies that the prefix location is unchanged.
/// 2. It verifies that the system requirements are met.
/// 3. It verifies the absence of the `env` folder.
pub fn sanity_check_project(project: &Project) -> miette::Result<()> {
// Sanity check of prefix location
verify_prefix_location_unchanged(
Expand Down
22 changes: 20 additions & 2 deletions src/project/manifest/feature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use rattler_conda_types::{NamelessMatchSpec, PackageName, Platform};
use serde::de::Error;
use serde::{Deserialize, Deserializer};
use serde_with::{serde_as, DisplayFromStr, PickFirst};
use std::borrow::Cow;
use std::borrow::{Borrow, Cow};
use std::collections::HashMap;
use std::fmt;

Expand All @@ -28,14 +28,22 @@ impl<'de> Deserialize<'de> for FeatureName {
D: serde::Deserializer<'de>,
{
match String::deserialize(deserializer)?.as_str() {
"default" => Err(D::Error::custom(
consts::DEFAULT_ENVIRONMENT_NAME => Err(D::Error::custom(
"The name 'default' is reserved for the default feature",
)),
name => Ok(FeatureName::Named(name.to_string())),
}
}
}

impl<'s> From<&'s str> for FeatureName {
fn from(value: &'s str) -> Self {
match value {
consts::DEFAULT_ENVIRONMENT_NAME => FeatureName::Default,
name => FeatureName::Named(name.to_string()),
}
}
}
impl FeatureName {
/// Returns the name of the feature or `None` if this is the default feature.
pub fn name(&self) -> Option<&str> {
Expand All @@ -44,6 +52,16 @@ impl FeatureName {
FeatureName::Named(name) => Some(name),
}
}

pub fn as_str(&self) -> &str {
self.name().unwrap_or(consts::DEFAULT_ENVIRONMENT_NAME)
}
}

impl Borrow<str> for FeatureName {
fn borrow(&self) -> &str {
self.as_str()
}
}

impl From<FeatureName> for String {
Expand Down
Loading

0 comments on commit 6746b43

Please sign in to comment.