diff --git a/Cargo.lock b/Cargo.lock index 3c17992a4..66a944705 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3839,9 +3839,9 @@ dependencies = [ [[package]] name = "rattler" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd22dfa274c4d52295491906de6eaebc7e50ad60ffa63f15923f7a5c86278b09" +checksum = "7365abb0dff1cc5dce7d5b54accfbaccaca512216557a860a59099b2e41872cd" dependencies = [ "anyhow", "clap", @@ -3880,9 +3880,9 @@ dependencies = [ [[package]] name = "rattler_cache" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e57222ac28f224f675de54452b239f532e4f55ea36836526ae75e5a73cce01" +checksum = "e6fcc7980d8b4f0422145abbaec1f9f05ebd6e59f97fe4e5f9ba17fe2cf3846d" dependencies = [ "anyhow", "dashmap", @@ -3908,9 +3908,9 @@ dependencies = [ [[package]] name = "rattler_conda_types" -version = "0.29.0" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3679ee51d7869950d778b2acab10df50fa0b52a0acbb00d9ca95e880e5a2bb95" +checksum = "f70c3e619609920f0fc792743e427f012d449951a951c16154fea8ee2a957a48" dependencies = [ "chrono", "dirs", @@ -3961,9 +3961,9 @@ dependencies = [ [[package]] name = "rattler_lock" -version = "0.22.29" +version = "0.22.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6306c5177363f6f28803ed2dd9d31612771c12a47e7c83133833f4bcb7bc6194" +checksum = "0db0f03a38c93f291acc3df137fa5e4717da5de36ed4164f0dfdb657977619e0" dependencies = [ "chrono", "file_url", @@ -4023,9 +4023,9 @@ dependencies = [ [[package]] name = "rattler_package_streaming" -version = "0.22.11" +version = "0.22.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c46c1c690a668ed3bb740b078192301931a99126d4892748839535f2018b0c81" +checksum = "b31f201486e1fb6baec82edc39ccb87c75f00750357535031e261b11a091e738" dependencies = [ "bzip2", "chrono", @@ -4062,9 +4062,9 @@ dependencies = [ [[package]] name = "rattler_repodata_gateway" -version = "0.21.19" +version = "0.21.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9398d9e0a091286617c92f3a9f0c37c868371c9d9fd4cb46463d5d2a622fec3" +checksum = "f8193bd9d22c286dd30226fe49590d51e2f1391112480f513d9a037b3df54eee" dependencies = [ "anyhow", "async-compression", @@ -4117,11 +4117,12 @@ dependencies = [ [[package]] name = "rattler_shell" -version = "0.22.5" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dc935692eedf40b7135827b0eca92872b4f26c321c8a47d6f59d5fd99aaf09" +checksum = "c7bbe53732a38f9f60f88e90dc2daed73d487e02693d7326e6562cf58a484377" dependencies = [ "enum_dispatch", + "fs-err 3.0.0", "indexmap 2.6.0", "itertools 0.13.0", "rattler_conda_types", @@ -4135,9 +4136,9 @@ dependencies = [ [[package]] name = "rattler_solve" -version = "1.2.0" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73e8e5d356515cc815cd514255ac99c061ee770a6f3d087062a4bb6b0edd4a9a" +checksum = "84aaa6a08621e4850aabf242e67ce5ee68f12137c1a6e9f976c00d93c3c7891a" dependencies = [ "chrono", "futures", @@ -4154,9 +4155,9 @@ dependencies = [ [[package]] name = "rattler_virtual_packages" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dea1e5f560e837bba8c540c4595f4fc59a6671549637bf94aa6626c2cc519f7" +checksum = "a0b824df805e5b5fd581f93770fba032cf6d2f95a7e8249972a6fcf5f464f46a" dependencies = [ "archspec", "libloading", @@ -4432,9 +4433,9 @@ dependencies = [ [[package]] name = "resolvo" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec9678b31efe58ba8cb322a6acf8fc85d1ee2b0f16cea5bc2c8aa990c2f8a9" +checksum = "03fdd3aa47ae0816ce4ec203eba1330e7c96a6760cbfbee5f1d2ca6e768b50f7" dependencies = [ "ahash", "bitvec", diff --git a/Cargo.toml b/Cargo.toml index 082675151..f271910e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -96,18 +96,18 @@ uv-requirements-txt = { git = "https://github.com/astral-sh/uv", tag = "0.4.30" # Rattler crates file_url = "0.1.4" -rattler = { version = "0.28.0", default-features = false } -rattler_cache = { version = "0.2.7", default-features = false } -rattler_conda_types = { version = "0.29.0", default-features = false } -rattler_digest = { version = "1.0.2", default-features = false } -rattler_lock = { version = "0.22.29", default-features = false } +rattler = { version = "0.28.1", default-features = false } +rattler_cache = { version = "0.2.9", default-features = false } +rattler_conda_types = { version = "0.29.1", default-features = false } +rattler_digest = { version = "1.0.3", default-features = false } +rattler_lock = { version = "0.22.30", default-features = false } rattler_networking = { version = "0.21.5", default-features = false, features = [ "google-cloud-auth", ] } -rattler_repodata_gateway = { version = "0.21.18", default-features = false } -rattler_shell = { version = "0.22.4", default-features = false } -rattler_solve = { version = "1.1.0", default-features = false } -rattler_virtual_packages = { version = "1.1.7", default-features = false } +rattler_repodata_gateway = { version = "0.21.21", default-features = false } +rattler_shell = { version = "0.22.6", default-features = false } +rattler_solve = { version = "1.2.2", default-features = false } +rattler_virtual_packages = { version = "1.1.9", default-features = false } # Bumping this to a higher version breaks the Windows path handling. url = "2.5.2" @@ -241,7 +241,7 @@ uv-pep508 = { workspace = true } uv-pypi-types = { workspace = true } fs-err = { workspace = true, features = ["tokio"] } -pixi_config = { workspace = true, features = ["rattler_repodata_gateway"] } +pixi_config = { workspace = true } pixi_consts = { workspace = true } pixi_default_versions = { workspace = true } pixi_manifest = { workspace = true } @@ -333,26 +333,30 @@ reqwest-retry = { git = "https://github.com/TrueLayer/reqwest-middleware", rev = # pep440_rs = { git = "https://github.com/astral-sh/uv", tag = "0.4.30" } # pep508_rs = { git = "https://github.com/astral-sh/uv", tag = "0.4.30" } # deno_task_shell = { path = "../deno_task_shell" } -# rattler = { git = "https://github.com/conda/rattler", branch = "main" } -# rattler_conda_types = { git = "https://github.com/conda/rattler", branch = "main" } -# rattler_digest = { git = "https://github.com/conda/rattler", branch = "main" } -# rattler_lock = { git = "https://github.com/conda/rattler", branch = "main" } -# rattler_networking = { git = "https://github.com/conda/rattler", branch = "main" } -# rattler_repodata_gateway = { git = "https://github.com/conda/rattler", branch = "main" } -# rattler_shell = { git = "https://github.com/conda/rattler", branch = "main" } -# rattler_solve = { git = "https://github.com/conda/rattler", branch = "main" } -# rattler_virtual_packages = { git = "https://github.com/conda/rattler", branch = "main" } + +#rattler = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" } +#rattler_cache = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" } +#rattler_conda_types = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" } +#rattler_digest = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" } +#rattler_lock = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" } +#rattler_networking = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" } +#rattler_package_streaming = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" } +#rattler_repodata_gateway = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" } +#rattler_shell = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" } +#rattler_solve = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" } +#rattler_virtual_packages = { git = "https://github.com/baszalmstra/rattler", branch = "perf/prefix-always-sharded" } + +#rattler = { path = "../rattler/crates/rattler" } +#rattler_cache = { path = "../rattler/crates/rattler_cache" } #rattler_conda_types = { path = "../rattler/crates/rattler_conda_types" } #rattler_digest = { path = "../rattler/crates/rattler_digest" } +#rattler_lock = { path = "../rattler/crates/rattler_lock" } #rattler_networking = { path = "../rattler/crates/rattler_networking" } +#rattler_package_streaming = { path = "../rattler/crates/rattler_package_streaming" } #rattler_repodata_gateway = { path = "../rattler/crates/rattler_repodata_gateway" } #rattler_shell = { path = "../rattler/crates/rattler_shell" } #rattler_solve = { path = "../rattler/crates/rattler_solve" } #rattler_virtual_packages = { path = "../rattler/crates/rattler_virtual_packages" } -#rattler_lock = { path = "../rattler/crates/rattler_lock" } -#rattler_package_streaming = { path = "../rattler/crates/rattler_package_streaming" } -#rattler = { path = "../rattler/crates/rattler" } - # Change these lines if you want a patched version of uv # [patch.'https://github.com/astral-sh/uv'] diff --git a/crates/pixi_config/Cargo.toml b/crates/pixi_config/Cargo.toml index c0762d3fd..47772f06a 100644 --- a/crates/pixi_config/Cargo.toml +++ b/crates/pixi_config/Cargo.toml @@ -18,9 +18,7 @@ miette = { workspace = true } pixi_consts = { workspace = true } rattler = { workspace = true } rattler_conda_types = { workspace = true } -rattler_repodata_gateway = { workspace = true, optional = true, features = [ - "gateway", -] } +rattler_repodata_gateway = { workspace = true, features = ["gateway"] } reqwest-middleware = { workspace = true } serde = { workspace = true } serde_ignored = { workspace = true } diff --git a/crates/pixi_config/src/lib.rs b/crates/pixi_config/src/lib.rs index 968b3f75f..be80ec53a 100644 --- a/crates/pixi_config/src/lib.rs +++ b/crates/pixi_config/src/lib.rs @@ -15,9 +15,7 @@ use rattler_conda_types::{ version_spec::{EqualityOperator, LogicalOperator, RangeOperator}, ChannelConfig, NamedChannelOrUrl, Version, VersionBumpType, VersionSpec, }; -#[cfg(feature = "rattler_repodata_gateway")] use rattler_repodata_gateway::{Gateway, SourceConfig}; -#[cfg(feature = "rattler_repodata_gateway")] use reqwest_middleware::ClientWithMiddleware; use serde::{de::IntoDeserializer, Deserialize, Serialize}; use url::Url; @@ -72,7 +70,8 @@ pub fn home_path() -> Option { } } -// TODO(tim): I think we should move this to another crate, dont know if global config is really correct +// TODO(tim): I think we should move this to another crate, dont know if global +// config is really correct /// Returns the default cache directory. /// Most important is the `PIXI_CACHE_DIR` environment variable. /// - If that is not set, the `RATTLER_CACHE_DIR` environment variable is used. @@ -132,9 +131,46 @@ impl ConfigCliPrompt { } } +#[derive(Clone, Default, Debug, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub struct RepodataConfig { + #[serde(flatten)] + default: RepodataChannelConfig, + + #[serde(flatten)] + per_channel: HashMap, +} + +impl RepodataConfig { + pub fn is_empty(&self) -> bool { + self.default.is_empty() && self.per_channel.is_empty() + } + + /// Merge the given RepodataConfig into the current one. + /// `other` is mutable to allow for moving the values out of it. + pub fn merge(&self, mut other: Self) -> Self { + let mut per_channel: HashMap<_, _> = self + .per_channel + .clone() + .into_iter() + .map(|(url, config)| { + let other_config = other.per_channel.remove(&url).unwrap_or_default(); + (url, config.merge(other_config)) + }) + .collect(); + + per_channel.extend(other.per_channel); + + Self { + default: self.default.merge(other.default), + per_channel, + } + } +} + #[derive(Clone, Default, Debug, Deserialize, Serialize)] #[serde(deny_unknown_fields, rename_all = "kebab-case")] -pub struct RepodataConfig { +pub struct RepodataChannelConfig { /// Disable JLAP compression for repodata. #[serde(alias = "disable_jlap")] // BREAK: remove to stop supporting snake_case alias #[serde(skip_serializing_if = "Option::is_none")] @@ -147,6 +183,40 @@ pub struct RepodataConfig { #[serde(alias = "disable_zstd")] // BREAK: remove to stop supporting snake_case alias #[serde(skip_serializing_if = "Option::is_none")] pub disable_zstd: Option, + /// Disable the use of sharded repodata + #[serde(skip_serializing_if = "Option::is_none")] + pub disable_sharded: Option, +} + +impl RepodataChannelConfig { + pub fn is_empty(&self) -> bool { + self.disable_jlap.is_none() + && self.disable_bzip2.is_none() + && self.disable_zstd.is_none() + && self.disable_sharded.is_none() + } + + pub fn merge(&self, other: Self) -> Self { + Self { + disable_jlap: self.disable_jlap.or(other.disable_jlap), + disable_zstd: self.disable_zstd.or(other.disable_zstd), + disable_bzip2: self.disable_bzip2.or(other.disable_bzip2), + disable_sharded: self.disable_sharded.or(other.disable_sharded), + } + } +} + +impl From for SourceConfig { + fn from(value: RepodataChannelConfig) -> Self { + SourceConfig { + jlap_enabled: !value.disable_jlap.unwrap_or(false), + zstd_enabled: !value.disable_zstd.unwrap_or(false), + bz2_enabled: !value.disable_bzip2.unwrap_or(false), + // TODO: Change sharded repodata default to true, when enough testing has been done. + sharded_enabled: !value.disable_sharded.unwrap_or(true), + cache_action: Default::default(), + } + } } #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, clap::ValueEnum)] @@ -394,8 +464,8 @@ pub struct Config { /// Configuration for repodata fetching. #[serde(alias = "repodata_config")] // BREAK: remove to stop supporting snake_case alias - #[serde(skip_serializing_if = "Option::is_none")] - pub repodata_config: Option, + #[serde(default, skip_serializing_if = "RepodataConfig::is_empty")] + pub repodata_config: RepodataConfig, /// Configuration for PyPI packages. #[serde(default)] @@ -421,7 +491,7 @@ impl Default for Config { mirrors: HashMap::new(), loaded_from: Vec::new(), channel_config: default_channel_config(), - repodata_config: None, + repodata_config: RepodataConfig::default(), pypi_config: PyPIConfig::default(), detached_environments: Some(DetachedEnvironments::default()), pinning_strategy: Default::default(), @@ -444,30 +514,31 @@ impl From for Config { } } -#[cfg(feature = "rattler_repodata_gateway")] impl From for rattler_repodata_gateway::ChannelConfig { fn from(config: Config) -> Self { rattler_repodata_gateway::ChannelConfig::from(&config) } } -#[cfg(feature = "rattler_repodata_gateway")] impl From<&Config> for rattler_repodata_gateway::ChannelConfig { fn from(config: &Config) -> Self { - let default_source_config = config - .repodata_config - .as_ref() - .map(|config| SourceConfig { - jlap_enabled: !config.disable_jlap.unwrap_or(false), - zstd_enabled: !config.disable_zstd.unwrap_or(false), - bz2_enabled: !config.disable_bzip2.unwrap_or(false), - cache_action: Default::default(), + let repodata_config = &config.repodata_config; + let default = repodata_config.default.clone().into(); + + let per_channel = repodata_config + .per_channel + .iter() + .map(|(url, config)| { + ( + url.clone(), + config.merge(repodata_config.default.clone()).into(), + ) }) - .unwrap_or_default(); + .collect(); rattler_repodata_gateway::ChannelConfig { - default: default_source_config, - per_channel: Default::default(), + default, + per_channel, } } } @@ -656,6 +727,7 @@ impl Config { "repodata-config.disable-jlap", "repodata-config.disable-bzip2", "repodata-config.disable-zstd", + "repodata-config.disable-sharded", "pypi-config", "pypi-config.index-url", "pypi-config.extra-index-urls", @@ -684,7 +756,7 @@ impl Config { loaded_from: self.loaded_from, // currently this is always the default so just use the other value channel_config: other.channel_config, - repodata_config: other.repodata_config.or(self.repodata_config), + repodata_config: other.repodata_config.merge(self.repodata_config), pypi_config: other.pypi_config.merge(self.pypi_config), detached_environments: other.detached_environments.or(self.detached_environments), pinning_strategy: other.pinning_strategy.or(self.pinning_strategy), @@ -728,8 +800,8 @@ impl Config { &self.channel_config } - pub fn repodata_config(&self) -> Option<&RepodataConfig> { - self.repodata_config.as_ref() + pub fn repodata_config(&self) -> &RepodataConfig { + &self.repodata_config } pub fn pypi_config(&self) -> &PyPIConfig { @@ -801,7 +873,8 @@ impl Config { self.repodata_config = value .map(|v| serde_json::de::from_str(&v)) .transpose() - .into_diagnostic()?; + .into_diagnostic()? + .unwrap_or_default(); return Ok(()); } else if !key.starts_with("repodata-config.") { return Err(err); @@ -810,21 +883,19 @@ impl Config { let subkey = key.strip_prefix("repodata-config.").unwrap(); match subkey { "disable-jlap" => { - self.repodata_config - .get_or_insert(RepodataConfig::default()) - .disable_jlap = + self.repodata_config.default.disable_jlap = value.map(|v| v.parse()).transpose().into_diagnostic()?; } "disable-bzip2" => { - self.repodata_config - .get_or_insert(RepodataConfig::default()) - .disable_bzip2 = + self.repodata_config.default.disable_bzip2 = value.map(|v| v.parse()).transpose().into_diagnostic()?; } "disable-zstd" => { - self.repodata_config - .get_or_insert(RepodataConfig::default()) - .disable_zstd = + self.repodata_config.default.disable_zstd = + value.map(|v| v.parse()).transpose().into_diagnostic()?; + } + "disable-sharded" => { + self.repodata_config.default.disable_sharded = value.map(|v| v.parse()).transpose().into_diagnostic()?; } _ => return Err(err), @@ -893,7 +964,6 @@ impl Config { } /// Constructs a [`Gateway`] using a [`ClientWithMiddleware`] - #[cfg(feature = "rattler_repodata_gateway")] pub fn gateway(&self, client: ClientWithMiddleware) -> Gateway { // Determine the cache directory and fall back to sane defaults otherwise. let cache_dir = get_cache_dir().unwrap_or_else(|e| { @@ -1137,10 +1207,11 @@ UNUSED = "unused" .get(&Url::parse("https://conda.anaconda.org/conda-forge").unwrap()), Some(&vec![Url::parse("https://prefix.dev/conda-forge").unwrap()]) ); - let repodata_config = config.repodata_config.unwrap(); - assert_eq!(repodata_config.disable_jlap, Some(true)); - assert_eq!(repodata_config.disable_bzip2, Some(true)); - assert_eq!(repodata_config.disable_zstd, Some(true)); + let repodata_config = config.repodata_config; + assert_eq!(repodata_config.default.disable_jlap, Some(true)); + assert_eq!(repodata_config.default.disable_bzip2, Some(true)); + assert_eq!(repodata_config.default.disable_zstd, Some(true)); + assert_eq!(repodata_config.default.disable_sharded, None); // See if the toml parses in kebab-case let toml = r#" default-channels = ["conda-forge"] @@ -1155,6 +1226,7 @@ UNUSED = "unused" disable-jlap = true disable-bzip2 = true disable-zstd = true + disable-sharded = true "#; Config::from_toml(toml).unwrap(); } @@ -1218,8 +1290,8 @@ UNUSED = "unused" config .set("repodata-config.disable-jlap", Some("true".to_string())) .unwrap(); - let repodata_config = config.repodata_config().unwrap(); - assert_eq!(repodata_config.disable_jlap, Some(true)); + let repodata_config = config.repodata_config(); + assert_eq!(repodata_config.default.disable_jlap, Some(true)); config .set( @@ -1333,4 +1405,51 @@ UNUSED = "unused" .join("\n"); insta::assert_snapshot!(results); } + + #[test] + fn test_repodata_config() { + let toml = r#" + [repodata-config] + disable-jlap = true + disable-bzip2 = true + disable-zstd = true + disable-sharded = true + + [repodata-config."https://prefix.dev/conda-forge"] + disable-jlap = false + disable-bzip2 = false + disable-zstd = false + disable-sharded = false + + [repodata-config."https://conda.anaconda.org/conda-forge"] + disable-jlap = false + disable-bzip2 = false + disable-zstd = false + "#; + let (config, _) = Config::from_toml(toml).unwrap(); + let repodata_config = config.repodata_config(); + assert_eq!(repodata_config.default.disable_jlap, Some(true)); + assert_eq!(repodata_config.default.disable_bzip2, Some(true)); + assert_eq!(repodata_config.default.disable_zstd, Some(true)); + assert_eq!(repodata_config.default.disable_sharded, Some(true)); + + let per_channel = repodata_config.clone().per_channel; + assert_eq!(per_channel.len(), 2); + + let prefix_config = per_channel + .get(&Url::from_str("https://prefix.dev/conda-forge").unwrap()) + .unwrap(); + assert_eq!(prefix_config.disable_jlap, Some(false)); + assert_eq!(prefix_config.disable_bzip2, Some(false)); + assert_eq!(prefix_config.disable_zstd, Some(false)); + assert_eq!(prefix_config.disable_sharded, Some(false)); + + let anaconda_config = per_channel + .get(&Url::from_str("https://conda.anaconda.org/conda-forge").unwrap()) + .unwrap(); + assert_eq!(anaconda_config.disable_jlap, Some(false)); + assert_eq!(anaconda_config.disable_bzip2, Some(false)); + assert_eq!(anaconda_config.disable_zstd, Some(false)); + assert_eq!(anaconda_config.disable_sharded, None); + } } diff --git a/crates/pixi_config/src/snapshots/pixi_config__tests__config_merge.snap b/crates/pixi_config/src/snapshots/pixi_config__tests__config_merge.snap index e44c67974..8ed30d9b7 100644 --- a/crates/pixi_config/src/snapshots/pixi_config__tests__config_merge.snap +++ b/crates/pixi_config/src/snapshots/pixi_config__tests__config_merge.snap @@ -45,8 +45,8 @@ Config { }, root_dir: "/root/dir", }, - repodata_config: Some( - RepodataConfig { + repodata_config: RepodataConfig { + default: RepodataChannelConfig { disable_jlap: Some( true, ), @@ -54,8 +54,10 @@ Config { disable_zstd: Some( true, ), + disable_sharded: None, }, - ), + per_channel: {}, + }, pypi_config: PyPIConfig { index_url: None, extra_index_urls: [], diff --git a/crates/pixi_spec/src/lib.rs b/crates/pixi_spec/src/lib.rs index f2e8b9298..df8a6e2f4 100644 --- a/crates/pixi_spec/src/lib.rs +++ b/crates/pixi_spec/src/lib.rs @@ -121,7 +121,7 @@ impl PixiSpec { build_number: spec.build_number, file_name: spec.file_name, channel: spec.channel.map(|c| { - NamedChannelOrUrl::from_str(&channel_config.canonical_name(c.base_url())) + NamedChannelOrUrl::from_str(&channel_config.canonical_name(c.base_url.url())) .unwrap() }), subdir: spec.subdir, diff --git a/crates/pixi_utils/src/snapshots/pixi_utils__conda_environment_file__tests__test_import_from_env_yaml.cockpit.yml.snap b/crates/pixi_utils/src/snapshots/pixi_utils__conda_environment_file__tests__test_import_from_env_yaml.cockpit.yml.snap index 3a654fae5..df12116de 100644 --- a/crates/pixi_utils/src/snapshots/pixi_utils__conda_environment_file__tests__test_import_from_env_yaml.cockpit.yml.snap +++ b/crates/pixi_utils/src/snapshots/pixi_utils__conda_environment_file__tests__test_import_from_env_yaml.cockpit.yml.snap @@ -1,6 +1,6 @@ --- source: crates/pixi_utils/src/conda_environment_file.rs -expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n parse_channels(env_info.channels().clone()), env_info.name())" +expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\nparse_channels(env_info.channels().clone()), env_info.name())" --- ( ( @@ -55,21 +55,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/pytorch/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/pytorch/, name: Some( "pytorch", ), @@ -95,21 +81,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/pytorch/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/pytorch/, name: Some( "pytorch", ), @@ -135,21 +107,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -175,21 +133,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -215,21 +159,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -255,21 +185,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -295,21 +211,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -335,21 +237,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -375,21 +263,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -415,21 +289,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -455,21 +315,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -495,21 +341,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -535,21 +367,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -575,21 +393,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -615,21 +419,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -655,21 +445,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -695,21 +471,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -745,21 +507,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), @@ -785,21 +533,7 @@ expression: "(parse_dependencies(env_info.dependencies().clone()).unwrap(),\n channel: Some( Channel { platforms: None, - base_url: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), - ), - port: None, - path: "/conda-forge/", - query: None, - fragment: None, - }, + base_url: https://conda.anaconda.org/conda-forge/, name: Some( "conda-forge", ), diff --git a/docs/reference/pixi_configuration.md b/docs/reference/pixi_configuration.md index c9baf567a..b6901b9f5 100644 --- a/docs/reference/pixi_configuration.md +++ b/docs/reference/pixi_configuration.md @@ -192,6 +192,13 @@ Configuration for repodata fetching. disable-jlap = true # don't try to download repodata.jlap disable-bzip2 = true # don't try to download repodata.json.bz2 disable-zstd = true # don't try to download repodata.json.zst +disable-sharded = true # don't try to download sharded repodata +``` + +The above settings can be overridden on a per-channel basis by specifying a channel prefix in the configuration. +```toml title="config.toml" +[repodata-config."https://prefix.dev"] +disable-sharded = false ``` ### `pypi-config` diff --git a/src/cli/exec.rs b/src/cli/exec.rs index 645502d2a..586e107ba 100644 --- a/src/cli/exec.rs +++ b/src/cli/exec.rs @@ -67,7 +67,7 @@ impl EnvironmentHash { .channels .resolve_from_config(config)? .iter() - .map(|c| c.base_url().to_string()) + .map(|c| c.base_url.to_string()) .collect(), }) } diff --git a/src/lock_file/satisfiability.rs b/src/lock_file/satisfiability.rs index 34dfba6b5..50208905b 100644 --- a/src/lock_file/satisfiability.rs +++ b/src/lock_file/satisfiability.rs @@ -17,7 +17,7 @@ use pixi_uv_conversions::{ }; use pypi_modifiers::pypi_marker_env::determine_marker_environment; use rattler_conda_types::{ - GenericVirtualPackage, MatchSpec, Matches, NamedChannelOrUrl, ParseChannelError, + ChannelUrl, GenericVirtualPackage, MatchSpec, Matches, NamedChannelOrUrl, ParseChannelError, ParseMatchSpecError, ParseStrictness::Lenient, Platform, RepoDataRecord, }; use rattler_lock::{ @@ -321,25 +321,19 @@ pub fn verify_environment_satisfiability( // that the order matters here. If channels are added in a different order, // the solver might return a different result. let config = environment.project().channel_config(); - let channels: Vec = grouped_env + let channels: Vec = grouped_env .channels() .into_iter() - .map(|channel| { - channel - .clone() - .into_channel(&config) - .map(|channel| channel.base_url().clone()) - }) + .map(|channel| channel.clone().into_base_url(&config)) .try_collect()?; - let locked_channels: Vec = locked_environment + let locked_channels: Vec = locked_environment .channels() .iter() .map(|c| { NamedChannelOrUrl::from_str(&c.url) .unwrap_or_else(|_err| NamedChannelOrUrl::Name(c.url.clone())) - .into_channel(&config) - .map(|channel| channel.base_url().clone()) + .into_base_url(&config) }) .try_collect()?; if !channels.eq(&locked_channels) {