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

Remove dependency from feature through cli #680

Merged
merged 11 commits into from
Jan 18, 2024
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
23 changes: 21 additions & 2 deletions src/project/manifest/feature.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::{Activation, PyPiRequirement, SystemRequirements, Target, TargetSelector};
use crate::consts;
use crate::project::manifest::channel::{PrioritizedChannel, TomlPrioritizedChannelStrOrMap};
use crate::project::manifest::target::Targets;
use crate::project::SpecType;
Expand All @@ -10,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;

/// The name of a feature. This is either a string or default for the default feature.
Expand All @@ -26,14 +27,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 @@ -42,6 +51,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()
}
}

/// A feature describes a set of functionalities. It allows us to group functionality and its
Expand Down
Loading
Loading