From 3b9768a00fe9a458e134dad1e15bfd5742f46448 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 6 Jul 2026 08:20:32 +0000 Subject: [PATCH 1/5] refactor!: back pixi Config by rattler_config's ConfigBase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pixi's `Config` is no longer a parallel struct that duplicates the shared rattler configuration keys: it is now a thin `#[serde(transparent)]` wrapper around `rattler_config::config::ConfigBase` from the redesigned (unreleased) rattler_config, where `PixiConfig` is pixi's tool-specific extension. This proves out the shared-config extension mechanism end to end. What moved where: - Shared keys (default-channels, authentication-override-file, tls-no-verify, tls-root-certs, mirrors, build, channel-config, repodata-config, concurrency, proxy-config, s3-options, index-config, run-post-link-scripts, allow-symbolic/hard/ref-links, loaded_from) now live in the upstream `CommonConfig` / `ConfigBase` and are reached through `Deref` (`config.mirrors`, `config.concurrency`, ...). - Pixi-specific keys (pinning-strategy, pypi-config, detached-environments, shell, experimental, tool-platform, cache, and the deprecated change-ps1/force-activate) moved into the new `PixiConfig` extension (`config.extensions.*`), with all serde attributes (kebab-case, snake_case aliases, skip_serializing_if guards) carried over so the on-disk TOML format is unchanged. New accessors `shell()`, `experimental()`, `cache()`, `pinning_strategy()` keep call sites terse; existing accessors keep their signatures. - `tls_root_certs` is promoted to the upstream `rattler_config::config::tls::TlsRootCerts` (Webpki/System). The legacy "native"/"all" spellings deserialize as aliases of System, and pixi keeps its load-time deprecation warnings by inspecting the raw TOML document (`Config::from_toml`) and via a clap value parser for `--tls-root-certs` / `PIXI_TLS_ROOT_CERTS`. pixi_utils' feature-aware fallback logic (native-tls vs rustls) is unchanged; the LegacyNative/All match arms collapse into System. - allow-symbolic-links/allow-hard-links/allow-ref-links use the upstream CommonConfig fields (same flat key names, same format). Extensibility proof points (each covered by tests): - `Config::from_toml` uses `ConfigBase::::from_toml_str`, whose two-pass serde_ignored deserialization reports keys unknown to BOTH the common config and the extension, so the "Ignoring '...' in file" warnings keep working — including for typos of extension keys (`pinning-strateggy`) and unknown keys nested in known tables (`shell.chnge-ps1`, `pypi-config.index-urll`). New test: test_from_toml_reports_unknown_extension_keys. - `Config::set` now special-cases only the deprecated change-ps1/force-activate hard errors, detached-environments bool/path parsing (~-expansion), and the cache.* re-validation; the former ~400-line match is deleted and everything else — including extension keys like `pinning-strategy` — delegates to the upstream generic `ConfigBase::set` (TOML round-trip editor). Unknown keys produce an error listing all supported keys (shared + extension) from the `Config` trait's `keys()`. New test: test_generic_set_handles_extension_keys; also verified against the built CLI: `pixi config set pinning-strategy semver` writes `pinning-strategy = "semver"`. - `ProxyConfig::default()` no longer reads proxy env vars upstream, so pixi_config's tests are hermetic: the whole suite (including test_config_merge_multiple) now passes with and without HTTPS_PROXY/HTTP_PROXY set. Dependency patching: a `[patch.crates-io]` block redirects every rattler crate pixi consumes to the `claude/rattler-shared-config-design-m8d2gb` branch of conda/rattler (single copy of each crate, verified with `cargo tree -i rattler_conda_types`). TODO: remove once rattler_config 0.6 is released (see conda/rattler#2557) — this PR must not merge until then. Behavior changes (intentional, small): - `default_channels` is `Option>` upstream; `Config::default_channels()` keeps returning the configured list or the consts::DEFAULT_CHANNELS fallback, and from_toml normalizes an explicitly empty list to None to preserve the old merge semantics. - `mirrors` is an `IndexMap` (was HashMap): deterministic ordering; `mirror_map()` signature updated. - `loaded_from` now lists files in load order (lowest precedence first); it previously listed them in reverse. - Editing a subkey of a non-existent s3-options bucket used to be a silent no-op; the generic editor rejects it (S3Options requires all three fields). Setting the whole bucket first works as before. - `pixi config set concurrency ''` used to (buggily) write pypi-config; the generic editor handles it correctly. - PyPIConfig::is_default now also checks allow-insecure-host, so a pypi-config containing only allow-insecure-host is no longer dropped on save. - A file containing `tls-root-certs = "native"`/`"all"` still loads (with the same deprecation warning), but re-saving it writes the canonical `"system"`. Snapshot diff (config_merge_multiple): Debug output is now nested as ConfigBase { common, extensions, loaded_from }; default_channels prints as Some([...]); the (empty, serde-skipped) upstream index_config section appears; loaded_from order flipped as described above. All values are identical to the old snapshot. Tests: cargo test -p pixi_config (55 passed, with and without proxy env), cargo test -p pixi_utils (72 passed), cargo check --workspace --all-targets, cargo clippy -p pixi_config/pixi_utils/pixi_cli/ pixi_core/pixi_api/pixi_uv_context --all-targets clean, cargo fmt. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01EzYs4p6XJDj9QBcNB4ipR7 --- Cargo.lock | 149 +- Cargo.toml | 26 + .../tests/integration_rust/install_tests.rs | 2 +- crates/pixi_api/src/workspace/init/mod.rs | 4 +- crates/pixi_cli/src/config.rs | 28 +- crates/pixi_cli/src/shell.rs | 2 +- crates/pixi_cli/src/shell_hook.rs | 2 +- crates/pixi_config/Cargo.toml | 3 +- crates/pixi_config/src/lib.rs | 1553 +++++++---------- ..._config__tests__config_merge_multiple.snap | 301 ++-- crates/pixi_core/src/workspace/mod.rs | 26 +- .../pixi_core/src/workspace/workspace_mut.rs | 4 +- crates/pixi_utils/src/reqwest.rs | 14 +- crates/pixi_utils/src/tls.rs | 11 +- crates/pixi_uv_context/src/lib.rs | 4 +- 15 files changed, 949 insertions(+), 1180 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4c80446341..3b2d57d82b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -161,9 +161,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.103" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "apple-native-keyring-store" @@ -1597,9 +1597,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.6.6" +version = "4.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97bf4965940c2382204c0ded6dd3dd48c0c4e872f1e76fb1bf94f45991a2cb6a" +checksum = "e0a7a9bfdb35811f9e59832f0f05975114d2251b415fb534108e6f34060fd772" dependencies = [ "clap", ] @@ -1680,8 +1680,7 @@ dependencies = [ [[package]] name = "coalesced_map" version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fe09392885c9af28aed39c6ddd06e41b43dbe98a850ccf0abe3f88d7cc75de" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "dashmap", "tokio", @@ -2321,10 +2320,11 @@ dependencies = [ [[package]] name = "deno_task_shell" -version = "0.33.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd069c87eb3cdc25e9898fe633a07ec7f20218e92ad3e7eccab3db324764d4fb" +checksum = "a5724630e5d004297ca84920ef90cbf8a5459b06f8cd553e1a75d9f3ad5cd6fd" dependencies = [ + "anyhow", "bitflags 2.11.1", "deno_path_util", "futures", @@ -2483,7 +2483,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2517,7 +2517,7 @@ checksum = "ad5208a115eaba24916f7456929832e310a81518c641f93fee4f89aa93aa3675" dependencies = [ "cfg-if 1.0.4", "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2773,7 +2773,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2860,8 +2860,7 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "file_url" version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d8c8b9119e366c1b4103d3ca9b5e09cc5684ae14f1265d1472d0a7fbc61747" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "itertools 0.14.0", "percent-encoding", @@ -4018,9 +4017,9 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.18.5" +version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "993f007684f2e9727160da8b960ec161264703bfd1af084fd2e34d040c9a0dd4" +checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" dependencies = [ "console", "portable-atomic", @@ -4124,7 +4123,7 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82cb6a9f675da968c63b6208c641b9dca58fc0133ae53375736b1767b0cab8bd" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4177,9 +4176,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.31" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccfe6121cbe750cf81efa362d85c0bde7ea298ec43092d3a193baca59cdbd634" +checksum = "34f877a98676d2fb664698d74cc6a51ce6c484ce8c770f05d0108ec9090aeb46" dependencies = [ "defmt", "jiff-static", @@ -4195,9 +4194,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.31" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e165e897f662d428f3cd3828a919dbe067c2d42bb1031eede74ef9d27ecdedd2" +checksum = "0666b5ab5ecaca213fc2a85b8c0083d9004e84ee2d5f9a7e0017aaf50986f25f" dependencies = [ "proc-macro2", "quote", @@ -4550,7 +4549,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cfc352a66ba903c23239ef51e809508b6fc2b0f90e3476ac7a9ff47e863ae95" dependencies = [ "scopeguard", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4560,7 +4559,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "160f2eade097f30263b548aae5deb12ad349c909baa710fa24b92c9090b2e006" dependencies = [ "scopeguard", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4578,7 +4577,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a1886916523694cd6ea3d175f03a1e5010699a2a4cc13696d83d7bea1d80638" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5164,7 +5163,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5759,8 +5758,7 @@ checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" [[package]] name = "path_resolver" version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a6d8be98ef9723e752c20eef948d3195d4e1314bc3cc033a8ff26b4e31d660" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "ahash", "fs-err", @@ -5936,7 +5934,7 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pixi" -version = "0.72.2" +version = "0.72.0" dependencies = [ "astral-reqwest-middleware", "async-trait", @@ -5996,7 +5994,7 @@ dependencies = [ [[package]] name = "pixi-build-cmake" -version = "0.4.4" +version = "0.4.3" dependencies = [ "async-trait", "fs-err", @@ -6022,7 +6020,7 @@ dependencies = [ [[package]] name = "pixi-build-mojo" -version = "0.2.4" +version = "0.2.3" dependencies = [ "async-trait", "fs-err", @@ -6045,7 +6043,7 @@ dependencies = [ [[package]] name = "pixi-build-python" -version = "0.8.3" +version = "0.8.2" dependencies = [ "async-trait", "fs-err", @@ -6075,7 +6073,7 @@ dependencies = [ [[package]] name = "pixi-build-r" -version = "0.1.5" +version = "0.1.4" dependencies = [ "async-trait", "fs-err", @@ -6099,7 +6097,7 @@ dependencies = [ [[package]] name = "pixi-build-rattler-build" -version = "0.4.4" +version = "0.4.3" dependencies = [ "async-trait", "fs-err", @@ -6123,10 +6121,9 @@ dependencies = [ [[package]] name = "pixi-build-ros" -version = "0.6.5" +version = "0.6.3" dependencies = [ "astral-reqwest-middleware", - "astral-reqwest-retry", "async-trait", "fs-err", "http-cache-reqwest", @@ -6135,7 +6132,6 @@ dependencies = [ "miette 7.6.0", "pathdiff", "pixi_build_backend", - "pixi_build_discovery", "pixi_build_types", "pixi_glob", "rattler_build_jinja", @@ -6144,7 +6140,6 @@ dependencies = [ "rattler_conda_types", "regex", "reqwest", - "retry-policies", "roxmltree", "serde", "serde_json", @@ -6158,7 +6153,7 @@ dependencies = [ [[package]] name = "pixi-build-rust" -version = "0.5.4" +version = "0.5.3" dependencies = [ "async-trait", "cargo_toml", @@ -6651,7 +6646,6 @@ dependencies = [ "reqwest", "rstest", "serde", - "serde_ignored", "serde_json", "thiserror 2.0.18", "toml_edit 0.23.10+spec-1.0.0", @@ -7986,8 +7980,7 @@ dependencies = [ [[package]] name = "rattler" version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67961cc1ccb170208f10169542752dbe730353a874a13cb0749c13b960d72d5b" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "anyhow", "astral-reqwest-middleware", @@ -8307,8 +8300,7 @@ dependencies = [ [[package]] name = "rattler_cache" version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24205a6af611e71f346e5e170c32f00ce1a9b49077f699f18d8404e711dc2209" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "ahash", "anyhow", @@ -8341,8 +8333,7 @@ dependencies = [ [[package]] name = "rattler_conda_types" version = "0.47.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "385575f3cfb4b9ce40c13d90b37964c80d8b527b62514118e4783ae0717b3ebd" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "ahash", "core-foundation 0.10.1", @@ -8384,14 +8375,14 @@ dependencies = [ [[package]] name = "rattler_config" version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0afcf9763975148e4cc805653de9146ff3542535895e37cdb1a06b2dd3d681af" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ - "console", + "dirs", "fs-err", "indexmap 2.14.0", "rattler_conda_types", "serde", + "serde_ignored", "serde_json", "thiserror 2.0.18", "toml 1.1.2+spec-1.1.0", @@ -8402,8 +8393,7 @@ dependencies = [ [[package]] name = "rattler_digest" version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e4af3c4e8b0cf496e66a5f2e7244364409a20cd4338ad9b331bd7247de32b69" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "blake2 0.11.0-rc.6", "digest 0.11.3", @@ -8443,8 +8433,7 @@ dependencies = [ [[package]] name = "rattler_index" version = "0.30.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d078770093f35bfdd275aa0c34689ef989b76dcd37d4e3b31a668e98852e61" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "ahash", "anyhow", @@ -8483,8 +8472,7 @@ dependencies = [ [[package]] name = "rattler_lock" version = "0.31.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec8b22e87f14a9ca2e55061f71b1d51d2dfb4aa1766babb95f06f6218d6733a" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "ahash", "file_url", @@ -8512,8 +8500,7 @@ dependencies = [ [[package]] name = "rattler_macros" version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3d93067b745b200dd741e872f4160de24d1b972ee63db65e8a2cf6a447f1ff" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "quote", "syn", @@ -8522,8 +8509,7 @@ dependencies = [ [[package]] name = "rattler_menuinst" version = "0.2.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957dbd0e8fb9ed66dce0bd6922914fb8bf795a4334d92e2190f34314a0b1f170" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "configparser", "dirs", @@ -8553,8 +8539,7 @@ dependencies = [ [[package]] name = "rattler_networking" version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5014e4f5aedcbe01a83a5be0e8669b305adc82cc10985fc83f51c5fe07e0d198" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "ambient-id", "anyhow", @@ -8593,8 +8578,7 @@ dependencies = [ [[package]] name = "rattler_package_streaming" version = "0.26.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b4440ad7368a66ddd370a8160d8fb2a4d0a825b7a050f9c421dac350b37bed2" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "astral-reqwest-middleware", "astral-tokio-tar", @@ -8648,8 +8632,7 @@ dependencies = [ [[package]] name = "rattler_pty" version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19145200e8c578be6dca325fbacf375a57f86d4a7ccf85d2d8ee193ddfb10dd" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "libc", "nix 0.30.1", @@ -8660,8 +8643,7 @@ dependencies = [ [[package]] name = "rattler_redaction" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1893dff3da09d778304797291869b17287e35a785cd8bc58fb9cd4760ef51b" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "astral-reqwest-middleware", "reqwest", @@ -8671,8 +8653,7 @@ dependencies = [ [[package]] name = "rattler_repodata_gateway" version = "0.29.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd05b4c6fbad5fae62d1d67c22c2bb411a7d21a026aeb079893df1d6d157a61" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "ahash", "anyhow", @@ -8734,8 +8715,7 @@ dependencies = [ [[package]] name = "rattler_s3" version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2a55757ecde8f53a17bc176d13061dda08485e3d1197dd7d9338e04ec7a3ca" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "aws-config", "aws-credential-types", @@ -8751,8 +8731,7 @@ dependencies = [ [[package]] name = "rattler_shell" version = "0.27.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9794276d154c19579fe7982ab2c1e9a960f0d51e5e56cd8d9fafe36373a71dd3" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "anyhow", "enum_dispatch", @@ -8773,8 +8752,7 @@ dependencies = [ [[package]] name = "rattler_solve" version = "7.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a9bbdbf299cc4f9b363bd54a4e315be7e96c7645f0a75df5853405d0189ead6" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "futures", "hex", @@ -8792,8 +8770,7 @@ dependencies = [ [[package]] name = "rattler_upload" version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1e75ffc1d23661ac5ad6b25836f6918fe46dfe065c013123d08e97f63e6f57" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "astral-reqwest-middleware", "astral-reqwest-retry", @@ -8831,8 +8808,7 @@ dependencies = [ [[package]] name = "rattler_virtual_packages" version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312c7e886ca90e83d562cadfb3d88af9dcef42f7c2489dae569df84c4bd07890" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "archspec", "libloading", @@ -9428,7 +9404,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -9461,9 +9437,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.15.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ "web-time", "zeroize", @@ -9508,7 +9484,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs 1.0.8", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -10472,8 +10448,7 @@ dependencies = [ [[package]] name = "simple_spawn_blocking" version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55c0b0b683828aa9d4f5c0e59b0c856a12c30a65b5f1ca4292664734d76fa9c2" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" dependencies = [ "tokio", ] @@ -10844,10 +10819,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.2", + "getrandom 0.3.4", "once_cell", "rustix 1.1.4", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -10857,7 +10832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ "rustix 1.1.4", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -13228,7 +13203,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index f1b1eddd9d..20dcd3a130 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -276,6 +276,32 @@ version-ranges = { git = "https://github.com/astral-sh/pubgrub", rev = "d8efd776 # `astral-reqwest-middleware` (rattler, rattler-build, uv). reqwest-middleware = { path = "patches/reqwest_middleware_shim" } +# TODO: remove once rattler_config 0.6 is released (see conda/rattler#2557). +# pixi's `Config` is backed by the redesigned `rattler_config::ConfigBase`, +# which is not on crates.io yet. Every rattler crate that shares public types +# with `rattler_config` (directly or transitively) must come from the same +# source, otherwise cargo would build two copies of e.g. +# `rattler_conda_types` and the shared types would not unify. +file_url = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_cache = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_conda_types = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_config = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_digest = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_index = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_lock = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_menuinst = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_networking = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_package_streaming = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_redaction = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_repodata_gateway = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_s3 = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_shell = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_solve = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_upload = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +rattler_virtual_packages = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +simple_spawn_blocking = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } + # Strip debug info from dependencies: faster links, much smaller `target/`, # while keeping full debuggability for our own crates. # See https://matklad.github.io/2021/09/04/fast-rust-builds.html diff --git a/crates/pixi/tests/integration_rust/install_tests.rs b/crates/pixi/tests/integration_rust/install_tests.rs index f99ca657c0..fa80b5826f 100644 --- a/crates/pixi/tests/integration_rust/install_tests.rs +++ b/crates/pixi/tests/integration_rust/install_tests.rs @@ -197,7 +197,7 @@ async fn install_locked_with_config() { // Overwrite install location to a target directory let mut config = Config::default(); let target_dir = pixi.workspace_path().join("target"); - config.detached_environments = Some(DetachedEnvironments::Path(target_dir.clone())); + config.extensions.detached_environments = Some(DetachedEnvironments::Path(target_dir.clone())); fs_err::create_dir_all(target_dir.clone()).unwrap(); let config_path = pixi.workspace().unwrap().pixi_dir().join("config.toml"); diff --git a/crates/pixi_api/src/workspace/init/mod.rs b/crates/pixi_api/src/workspace/init/mod.rs index 59c92c6e44..a0b46f42fb 100644 --- a/crates/pixi_api/src/workspace/init/mod.rs +++ b/crates/pixi_api/src/workspace/init/mod.rs @@ -68,8 +68,8 @@ fn build_render_context(dir: &Path, options: &InitOptions, config: &Config) -> R author: get_default_author(), platforms: resolve_platforms(options), channels: resolve_channels_from_options(options, config), - index_url: config.pypi_config.index_url.clone(), - extra_index_urls: config.pypi_config.extra_index_urls.clone(), + index_url: config.pypi_config().index_url.clone(), + extra_index_urls: config.pypi_config().extra_index_urls.clone(), s3_options: config.s3_options.clone(), conda_pypi_mapping: options.conda_pypi_mapping.clone(), } diff --git a/crates/pixi_cli/src/config.rs b/crates/pixi_cli/src/config.rs index 752494e86b..8242faae91 100644 --- a/crates/pixi_cli/src/config.rs +++ b/crates/pixi_cli/src/config.rs @@ -287,13 +287,13 @@ fn alter_config( let channel = NamedChannelOrUrl::from_str(&input) .into_diagnostic() .context("invalid channel name")?; - let mut new_channels = config.default_channels.clone(); + let mut new_channels = config.default_channels.clone().unwrap_or_default(); if is_prepend { new_channels.insert(0, channel); } else { new_channels.push(channel); } - config.default_channels = new_channels; + config.common.default_channels = Some(new_channels); } "pypi-config.extra-index-urls" => { let input = url::Url::parse(&value.expect("value must be provided")) @@ -304,7 +304,7 @@ fn alter_config( } else { new_urls.push(input); } - config.pypi_config.extra_index_urls = new_urls; + config.extensions.pypi_config.extra_index_urls = new_urls; } _ => { let list_keys = ["default-channels", "pypi-config.extra-index-urls"]; @@ -330,19 +330,19 @@ fn partial_config(config: &mut Config, key: &str) -> miette::Result<()> { let mut new = Config::default(); match key { - "default-channels" => new.default_channels = config.default_channels.clone(), - "shell" => new.shell = config.shell.clone(), - "tls-no-verify" => new.tls_no_verify = config.tls_no_verify, + "default-channels" => new.common.default_channels = config.default_channels.clone(), + "shell" => new.extensions.shell = config.shell().clone(), + "tls-no-verify" => new.common.tls_no_verify = config.tls_no_verify, "authentication-override-file" => { - new.authentication_override_file = config.authentication_override_file.clone() + new.common.authentication_override_file = config.authentication_override_file.clone() } - "mirrors" => new.mirrors = config.mirrors.clone(), - "repodata-config" => new.repodata_config = config.repodata_config.clone(), - "pypi-config" => new.pypi_config = config.pypi_config.clone(), - "proxy-config" => new.proxy_config = config.proxy_config.clone(), - "allow-symbolic-links" => new.allow_symbolic_links = config.allow_symbolic_links, - "allow-hard-links" => new.allow_hard_links = config.allow_hard_links, - "allow-ref-links" => new.allow_ref_links = config.allow_ref_links, + "mirrors" => new.common.mirrors = config.mirrors.clone(), + "repodata-config" => new.common.repodata_config = config.repodata_config.clone(), + "pypi-config" => new.extensions.pypi_config = config.pypi_config().clone(), + "proxy-config" => new.common.proxy_config = config.proxy_config.clone(), + "allow-symbolic-links" => new.common.allow_symbolic_links = config.allow_symbolic_links, + "allow-hard-links" => new.common.allow_hard_links = config.allow_hard_links, + "allow-ref-links" => new.common.allow_ref_links = config.allow_ref_links, _ => { let keys = [ "default-channels", diff --git a/crates/pixi_cli/src/shell.rs b/crates/pixi_cli/src/shell.rs index 400080daed..c9a7bcdc6a 100644 --- a/crates/pixi_cli/src/shell.rs +++ b/crates/pixi_cli/src/shell.rs @@ -386,7 +386,7 @@ pub async fn execute(args: Args) -> miette::Result<()> { String::new() }; - let source_shell_completions = workspace.config().shell.source_completion_scripts(); + let source_shell_completions = workspace.config().shell().source_completion_scripts(); #[cfg(target_family = "windows")] let res = match interactive_shell { diff --git a/crates/pixi_cli/src/shell_hook.rs b/crates/pixi_cli/src/shell_hook.rs index 6fa34d248c..e9a1373c6f 100644 --- a/crates/pixi_cli/src/shell_hook.rs +++ b/crates/pixi_cli/src/shell_hook.rs @@ -99,7 +99,7 @@ async fn generate_activation_script( }) .into_diagnostic()?; - if project.config().shell.source_completion_scripts() + if project.config().shell().source_completion_scripts() && let Some(completions_dir) = shell.completion_script_location() { result diff --git a/crates/pixi_config/Cargo.toml b/crates/pixi_config/Cargo.toml index 3f4d06014b..2a804fea93 100644 --- a/crates/pixi_config/Cargo.toml +++ b/crates/pixi_config/Cargo.toml @@ -20,12 +20,11 @@ miette = { workspace = true } pixi_consts = { workspace = true } rattler = { workspace = true } rattler_conda_types = { workspace = true } -rattler_config = { workspace = true } +rattler_config = { workspace = true, features = ["edit"] } rattler_networking = { workspace = true, features = ["s3"] } rattler_repodata_gateway = { workspace = true, features = ["gateway"] } reqwest = { workspace = true } serde = { workspace = true } -serde_ignored = { workspace = true } serde_json = { workspace = true } thiserror = { workspace = true } toml_edit = { workspace = true, features = ["serde"] } diff --git a/crates/pixi_config/src/lib.rs b/crates/pixi_config/src/lib.rs index 2817c592e9..fe268bc778 100644 --- a/crates/pixi_config/src/lib.rs +++ b/crates/pixi_config/src/lib.rs @@ -1,5 +1,6 @@ use std::{ collections::{BTreeSet as Set, HashMap, HashSet}, + ops::{Deref, DerefMut}, path::{Path, PathBuf}, process::{Command, Stdio}, str::FromStr, @@ -7,6 +8,7 @@ use std::{ }; use clap::{ArgAction, Parser}; +use indexmap::IndexMap; use itertools::Itertools; use miette::{Context, IntoDiagnostic, miette}; use pixi_consts::consts; @@ -14,70 +16,40 @@ use rattler_conda_types::{ ChannelConfig, NamedChannelOrUrl, Platform, Version, VersionBumpType, VersionSpec, version_spec::{EqualityOperator, LogicalOperator, RangeOperator}, }; +use rattler_config::config::ConfigBase; +// Bring the shared `Config` trait methods (merge_config, keys, ...) of the +// rattler_config types into scope under a non-clashing name. +use rattler_config::config::Config as RattlerConfig; +use rattler_config::config::{CommonConfig, MergeError}; use rattler_networking::s3_middleware; use rattler_repodata_gateway::{Gateway, GatewayBuilder, SourceConfig}; use reqwest::{NoProxy, Proxy}; use serde::{Deserialize, Serialize, de::IntoDeserializer}; use url::Url; -const EXPERIMENTAL: &str = "experimental"; - /// Controls which root certificates to use for TLS connections. /// -/// Note: This setting only has an effect when pixi is built with the `rustls` feature. -/// When built with `native-tls`, system certificates are always used regardless of this setting. +/// This is the shared `rattler_config` type: the legacy pixi spellings +/// `"native"` and `"all"` are accepted as deserialization aliases of +/// [`TlsRootCerts::System`]. pixi still emits a deprecation warning when a +/// config file or the CLI uses one of the legacy spellings (see +/// [`Config::from_toml`]). /// -/// `SSL_CERT_FILE` / `SSL_CERT_DIR` (when set and valid) always take precedence over this setting. -#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)] -pub enum TlsRootCerts { - /// Use bundled Mozilla root certificates (portable, works everywhere). - #[serde(rename = "webpki")] - Webpki, - /// Use the system's native certificate store (includes corporate CAs). - #[default] - #[serde(rename = "system")] - System, - /// Deprecated spelling of [`Self::System`]. - /// - /// Configs that still set `tls-root-certs = "native"` deserialize into this - /// variant so we can emit a runtime warning pointing users at the new - /// spelling. Behaves identically to `System` at use sites. - #[deprecated(note = "use `tls-root-certs = \"system\"`")] - #[serde(rename = "native")] - LegacyNative, - /// Use both webpki and native certificates. - /// - /// Deprecated: uv 0.11 no longer supports merging the two trust stores via - /// its public API, so pixi can no longer plumb this through for uv's - /// reqwest clients. This variant now falls through to `System` at - /// runtime and emits a warning. Use `webpki` or `system` explicitly, - /// or set `SSL_CERT_FILE` / `SSL_CERT_DIR`. - #[deprecated( - note = "merging webpki + native roots is no longer supported: use `system`, `webpki`, or set SSL_CERT_FILE/DIR" - )] - #[serde(rename = "all")] - All, -} - -impl FromStr for TlsRootCerts { - type Err = serde::de::value::Error; - - fn from_str(s: &str) -> Result { - Self::deserialize(s.into_deserializer()) - } -} - -impl std::fmt::Display for TlsRootCerts { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - TlsRootCerts::Webpki => write!(f, "webpki"), - TlsRootCerts::System => write!(f, "system"), - #[allow(deprecated)] - TlsRootCerts::LegacyNative => write!(f, "native"), - #[allow(deprecated)] - TlsRootCerts::All => write!(f, "all"), - } - } +/// Note: this setting only has an effect when pixi is built with the `rustls` +/// feature. When built with `native-tls`, system certificates are always used +/// regardless of this setting. `SSL_CERT_FILE` / `SSL_CERT_DIR` (when set and +/// valid) always take precedence over this setting. +pub use rattler_config::config::tls::TlsRootCerts; + +/// Clap value parser for `--tls-root-certs` that keeps the deprecation +/// warning for the legacy `"native"` / `"all"` spellings, which the shared +/// [`TlsRootCerts`] enum silently accepts as aliases of `System`. +fn parse_tls_root_certs_cli( + raw: &str, +) -> Result { + let parsed = raw.parse()?; + warn_deprecated_tls_root_certs(raw, None); + Ok(parsed) } pub fn default_channel_config() -> ChannelConfig { @@ -142,7 +114,8 @@ static NETFS_REDIRECT_WARNED: LazyLock>> = /// don't have a [`Config`] handy. Per-kind cache directories that should /// honor workspace-level `[cache.*]` overrides must be resolved through /// [`Config::cache_dir_for`] instead. -static GLOBAL_CACHE_CONFIG: LazyLock = LazyLock::new(|| Config::load_global().cache); +static GLOBAL_CACHE_CONFIG: LazyLock = + LazyLock::new(|| Config::load_global().extensions.cache.clone()); /// Describes where the system + user-level config layer comes from. Built from /// [`ConfigSourceCli`] (which mirrors `--no-config` / `--config-file`) and @@ -728,7 +701,7 @@ pub struct ConfigCli { pub tls_no_verify: bool, /// Which TLS root certificates to use: 'webpki' (bundled Mozilla roots) or 'system' (system store). - #[arg(long, env = "PIXI_TLS_ROOT_CERTS", help_heading = consts::CLAP_CONFIG_OPTIONS)] + #[arg(long, env = "PIXI_TLS_ROOT_CERTS", value_parser = parse_tls_root_certs_cli, help_heading = consts::CLAP_CONFIG_OPTIONS)] pub tls_root_certs: Option, /// Use environment activation cache (experimental) @@ -745,20 +718,16 @@ pub struct ConfigCliPrompt { impl From for Config { fn from(cli: ConfigCliPrompt) -> Self { - Self { - shell: ShellConfig { - change_ps1: cli.change_ps1, - ..Default::default() - }, - ..Default::default() - } + let mut config = Config::default(); + config.extensions.shell.change_ps1 = cli.change_ps1; + config } } impl ConfigCliPrompt { pub fn merge_config(self, config: Config) -> Config { let mut config = config; - config.shell.change_ps1 = self.change_ps1.or(config.shell.change_ps1); + config.extensions.shell.change_ps1 = self.change_ps1.or(config.extensions.shell.change_ps1); config } } @@ -785,9 +754,9 @@ pub struct ConfigCliActivation { impl ConfigCliActivation { pub fn merge_config(self, config: Config) -> Config { let mut config = config; - config.shell.force_activate = Some(self.force_activate); + config.extensions.shell.force_activate = Some(self.force_activate); if self.no_completions { - config.shell.source_completion_scripts = Some(false); + config.extensions.shell.source_completion_scripts = Some(false); } config } @@ -991,6 +960,7 @@ impl PyPIConfig { self.index_url.is_none() && self.extra_index_urls.is_empty() && self.keyring_provider.is_none() + && self.allow_insecure_host.is_empty() } } @@ -1108,38 +1078,17 @@ impl PinningStrategy { // crates (pixi_core, pixi_global). pub use rattler_config::config::run_post_link_scripts::RunPostLinkScripts; -#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +/// Pixi-specific configuration keys, layered on top of the shared rattler +/// config as the *extension* type of [`ConfigBase`]. +/// +/// These keys live at the top level of the same `config.toml` document as the +/// shared keys of [`CommonConfig`]. The serde attributes (kebab-case names, +/// snake_case aliases, `skip_serializing_if` guards) are carried over +/// unchanged from the former monolithic `Config` struct so the on-disk format +/// stays identical. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] #[serde(rename_all = "kebab-case")] -pub struct Config { - #[serde(default)] - #[serde(alias = "default_channels")] // BREAK: remove to stop supporting snake_case alias - #[serde(skip_serializing_if = "Vec::is_empty")] - pub default_channels: Vec, - - /// Path to the file containing the authentication token. - #[serde(default)] - #[serde(alias = "authentication_override_file")] // BREAK: remove to stop supporting snake_case alias - #[serde(skip_serializing_if = "Option::is_none")] - pub authentication_override_file: Option, - - /// If set to true, pixi will not verify the TLS certificate of the server. - #[serde(default)] - #[serde(alias = "tls_no_verify")] // BREAK: remove to stop supporting snake_case alias - #[serde(skip_serializing_if = "Option::is_none")] - pub tls_no_verify: Option, - - /// Which TLS root certificates to use for HTTPS connections. - // TODO(rattler-config): promote — TLS root cert selection is a - // generic HTTPS knob, not pixi-specific. rattler_config now ships a - // `TlsRootCerts` enum (config::tls) we could re-export. - #[serde(default)] - #[serde(skip_serializing_if = "Option::is_none")] - pub tls_root_certs: Option, - - #[serde(default)] - #[serde(skip_serializing_if = "HashMap::is_empty")] - pub mirrors: HashMap>, - +pub struct PixiConfig { /// Dependency Pinning strategy used for dependency modification through /// automated logic like `pixi add` // TODO(rattler-config): promote — useful for any tool that @@ -1147,28 +1096,11 @@ pub struct Config { #[serde(skip_serializing_if = "Option::is_none")] pub pinning_strategy: Option, - #[serde(skip)] - #[serde(alias = "loaded_from")] // BREAK: remove to stop supporting snake_case alias - pub loaded_from: Vec, - - #[serde(skip, default = "default_channel_config")] - pub channel_config: ChannelConfig, - - /// Configuration for repodata fetching. - #[serde(alias = "repodata_config")] // BREAK: remove to stop supporting snake_case alias - #[serde(default, skip_serializing_if = "RepodataConfig::is_empty")] - pub repodata_config: RepodataConfig, - /// Configuration for PyPI packages. #[serde(default)] #[serde(skip_serializing_if = "PyPIConfig::is_default")] pub pypi_config: PyPIConfig, - /// Configuration for S3. - #[serde(default)] - #[serde(skip_serializing_if = "S3OptionsMap::is_empty")] - pub s3_options: S3OptionsMap, - /// The option to specify the directory where detached environments are /// stored. When using 'true', it defaults to the cache directory. /// When using a path, it uses the specified path. @@ -1187,46 +1119,6 @@ pub struct Config { #[serde(skip_serializing_if = "ExperimentalConfig::is_default")] pub experimental: ExperimentalConfig, - /// Concurrency configuration for pixi - #[serde(default)] - #[serde(skip_serializing_if = "ConcurrencyConfig::is_default")] - pub concurrency: ConcurrencyConfig, - - /// Run the post link scripts - #[serde(default)] - #[serde(skip_serializing_if = "Option::is_none")] - pub run_post_link_scripts: Option, - - /// If set to false, symbolic links will not be used during package installation. - // TODO(rattler-config): promote — package-install link strategy is - // not pixi-specific. rattler_config now ships `LinkConfig` - // (config::link_config) grouping these three flags. - #[serde(default)] - #[serde(skip_serializing_if = "Option::is_none")] - pub allow_symbolic_links: Option, - - /// If set to false, hard links will not be used during package installation. - // TODO(rattler-config): promote — see `LinkConfig` above. - #[serde(default)] - #[serde(skip_serializing_if = "Option::is_none")] - pub allow_hard_links: Option, - - /// If set to false, ref links (copy-on-write) will not be used during package installation. - // TODO(rattler-config): promote — see `LinkConfig` above. - #[serde(default)] - #[serde(skip_serializing_if = "Option::is_none")] - pub allow_ref_links: Option, - - /// Https/Http proxy configuration for pixi - #[serde(default)] - #[serde(skip_serializing_if = "ProxyConfig::is_default")] - pub proxy_config: ProxyConfig, - - /// Build configuration for pixi and rattler-build - #[serde(default)] - #[serde(skip_serializing_if = "BuildConfig::is_default")] - pub build: BuildConfig, - /// The platform to use when installing tools. /// /// When running on certain platforms, you might want to install build @@ -1248,66 +1140,130 @@ pub struct Config { ////////////////////// // Deprecated fields // ////////////////////// + /// Deprecated; folded into `shell.change-ps1` at load time. #[serde(default)] #[serde(alias = "change_ps1")] // BREAK: remove to stop supporting snake_case alias #[serde(skip_serializing_if = "Option::is_none")] pub change_ps1: Option, + /// Deprecated; folded into `shell.force-activate` at load time. #[serde(default)] #[serde(skip_serializing_if = "Option::is_none")] pub force_activate: Option, } -impl Default for Config { - fn default() -> Self { - Self { - default_channels: Vec::new(), - authentication_override_file: None, - tls_no_verify: None, - tls_root_certs: None, - mirrors: HashMap::new(), - loaded_from: Vec::new(), - channel_config: default_channel_config(), - repodata_config: RepodataConfig::default(), - pypi_config: PyPIConfig::default(), - s3_options: S3OptionsMap::default(), - detached_environments: None, - pinning_strategy: None, - shell: ShellConfig::default(), - experimental: ExperimentalConfig::default(), - concurrency: ConcurrencyConfig::default(), - run_post_link_scripts: None, - allow_symbolic_links: None, - allow_hard_links: None, - allow_ref_links: None, - proxy_config: ProxyConfig::default(), - build: BuildConfig::default(), - tool_platform: None, - cache: CacheConfig::default(), - - // Deprecated fields +impl RattlerConfig for PixiConfig { + /// Merge another configuration on top of this one. `other` takes + /// priority, matching the semantics of the former `Config::merge_config`. + fn merge_config(self, other: &Self) -> Result { + Ok(Self { + pinning_strategy: other.pinning_strategy.or(self.pinning_strategy), + pypi_config: self.pypi_config.merge(other.pypi_config.clone()), + detached_environments: other + .detached_environments + .clone() + .or(self.detached_environments), + shell: self.shell.merge(other.shell.clone()), + experimental: self.experimental.merge(other.experimental.clone()), + // NOTE: `self` wins here — this preserves the (long-standing) + // behavior of the former `Config::merge_config`. + tool_platform: self.tool_platform.or(other.tool_platform), + cache: self.cache.clone().merge(other.cache.clone()), + + // Deprecated fields are dropped on merge: `Config::from_toml` + // folds them into `shell.*` before configs are merged. change_ps1: None, force_activate: None, - } + }) + } + + /// The dotted TOML key paths of the pixi-specific keys, used by the + /// generic [`ConfigBase::set`] for its "supported keys" listing and + /// unknown-key detection. + fn keys(&self) -> Vec { + [ + "pinning-strategy", + "detached-environments", + "tool-platform", + "pypi-config.index-url", + "pypi-config.extra-index-urls", + "pypi-config.keyring-provider", + "pypi-config.allow-insecure-host", + "shell.change-ps1", + "shell.force-activate", + "shell.source-completion-scripts", + "experimental.use-environment-activation-cache", + "cache.root", + "cache.conda-packages", + "cache.repodata", + "cache.pypi-wheels", + "cache.pypi-mapping", + "cache.exec-environments", + "cache.build-tool-environments", + "cache.detached-environments", + "cache.netfs-redirect", + ] + .into_iter() + .map(String::from) + .collect() } } -/// Emit a deprecation warning when a config layer (file, CLI flag, or env var) -/// sets `tls-root-certs` to one of the deprecated spellings. +/// The pixi configuration: the shared rattler configuration +/// ([`CommonConfig`]) extended with the pixi-specific keys ([`PixiConfig`]). +/// +/// This is a thin wrapper around [`ConfigBase`] that carries +/// pixi's inherent methods (loading, merging semantics, cache resolution, +/// clap integration, ...). It dereferences to [`ConfigBase`], which itself +/// dereferences to [`CommonConfig`], so both the shared fields +/// (`config.mirrors`, `config.concurrency`, ...) and the extension +/// (`config.extensions.shell`, ...) remain directly accessible. +#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] +#[serde(transparent)] +pub struct Config { + inner: ConfigBase, +} + +impl Deref for Config { + type Target = ConfigBase; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl DerefMut for Config { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + +impl From> for Config { + fn from(inner: ConfigBase) -> Self { + Self { inner } + } +} + +/// Emit a deprecation warning when a config layer (file, CLI flag, or env +/// var) sets `tls-root-certs` to one of the deprecated spellings. +/// +/// The shared [`TlsRootCerts`] enum accepts `"native"` and `"all"` as plain +/// aliases of `System`, so the legacy spellings can no longer be detected +/// from the parsed value; callers pass the raw string instead +/// ([`Config::from_toml`] inspects the raw TOML document). /// /// `source` is included in the message so users can find where the bad value /// came from. Pass `None` for non-file sources (CLI / env). -fn warn_deprecated_tls_root_certs(value: Option, source: Option<&str>) { - #[allow(deprecated)] - let (old, advice): (&str, String) = match value { - Some(TlsRootCerts::LegacyNative) => ( +fn warn_deprecated_tls_root_certs(raw: &str, source: Option<&str>) { + let (old, advice): (&str, String) = match raw { + "native" => ( "tls-root-certs = \"native\"", format!( "rename to '{}'", console::style("tls-root-certs = \"system\"").green() ), ), - Some(TlsRootCerts::All) => ( + "all" => ( "tls-root-certs = \"all\"", format!( "merging webpki and system roots is no longer supported. \ @@ -1328,44 +1284,71 @@ fn warn_deprecated_tls_root_certs(value: Option, source: Option<&s } } +/// Emit the `tls-root-certs` deprecation warnings for a raw TOML document. +/// +/// The shared [`TlsRootCerts`] deserializer silently maps the legacy +/// `"native"` / `"all"` spellings to `System`, so the raw document is +/// inspected to keep the load-time warnings. +fn warn_deprecated_tls_root_certs_in_document(toml: &str, source_path: Option<&Path>) { + let Ok(document) = toml.parse::() else { + return; + }; + for key in ["tls-root-certs", "tls_root_certs"] { + if let Some(raw) = document.get(key).and_then(|v| v.as_str()) { + warn_deprecated_tls_root_certs( + raw, + source_path.map(|p| p.display().to_string()).as_deref(), + ); + } + } +} + impl From for Config { fn from(cli: ConfigCli) -> Self { - warn_deprecated_tls_root_certs(cli.tls_root_certs, None); - Self { - tls_no_verify: if cli.tls_no_verify { Some(true) } else { None }, - tls_root_certs: cli.tls_root_certs, - authentication_override_file: cli.auth_file, - pypi_config: cli - .pypi_keyring_provider - .map(|val| PyPIConfig::default().with_keyring(val)) - .unwrap_or_default(), - detached_environments: None, - concurrency: ConcurrencyConfig { - solves: cli - .concurrent_solves - .unwrap_or(ConcurrencyConfig::default().solves), - downloads: cli - .concurrent_downloads - .unwrap_or(ConcurrencyConfig::default().downloads), - }, - tool_platform: None, - run_post_link_scripts: if cli.run_post_link_scripts { - Some(RunPostLinkScripts::Insecure) - } else { - None - }, - experimental: ExperimentalConfig { - use_environment_activation_cache: if cli.use_environment_activation_cache { - Some(true) - } else { - None + // Note: the deprecation warning for legacy `--tls-root-certs` + // spellings fires in the clap value parser + // (`parse_tls_root_certs_cli`), where the raw string is available. + Config { + inner: ConfigBase { + common: CommonConfig { + tls_no_verify: if cli.tls_no_verify { Some(true) } else { None }, + tls_root_certs: cli.tls_root_certs, + authentication_override_file: cli.auth_file, + concurrency: ConcurrencyConfig { + solves: cli + .concurrent_solves + .unwrap_or(ConcurrencyConfig::default().solves), + downloads: cli + .concurrent_downloads + .unwrap_or(ConcurrencyConfig::default().downloads), + }, + run_post_link_scripts: if cli.run_post_link_scripts { + Some(RunPostLinkScripts::Insecure) + } else { + None + }, + allow_symbolic_links: cli.no_symbolic_links.then_some(false), + allow_hard_links: cli.no_hard_links.then_some(false), + allow_ref_links: cli.no_ref_links.then_some(false), + ..CommonConfig::default() }, + extensions: PixiConfig { + pypi_config: cli + .pypi_keyring_provider + .map(|val| PyPIConfig::default().with_keyring(val)) + .unwrap_or_default(), + experimental: ExperimentalConfig { + use_environment_activation_cache: if cli.use_environment_activation_cache { + Some(true) + } else { + None + }, + }, + pinning_strategy: cli.pinning_strategy, + ..PixiConfig::default() + }, + loaded_from: Vec::new(), }, - pinning_strategy: cli.pinning_strategy, - allow_symbolic_links: cli.no_symbolic_links.then_some(false), - allow_hard_links: cli.no_hard_links.then_some(false), - allow_ref_links: cli.no_ref_links.then_some(false), - ..Default::default() } } } @@ -1477,7 +1460,7 @@ impl Config { config.channel_config.channel_alias = Url::parse("https://prefix.dev").unwrap(); // Use conda-forge as the default channel - config.default_channels = vec![NamedChannelOrUrl::Name("conda-forge".into())]; + config.common.default_channels = Some(vec![NamedChannelOrUrl::Name("conda-forge".into())]); // Enable sharded repodata by default. config.repodata_config.default.disable_sharded = Some(false); @@ -1486,7 +1469,7 @@ impl Config { // win-arm64. This is a workaround for the fact that we don't have a // good win-arm64 toolchain yet. if Platform::current() == Platform::WinArm64 { - config.tool_platform = Some(Platform::Win64); + config.extensions.tool_platform = Some(Platform::Win64); } config @@ -1506,14 +1489,13 @@ impl Config { toml: &str, source_path: Option<&Path>, ) -> miette::Result<(Config, Set)> { - let de = toml_edit::de::Deserializer::from_str(toml).into_diagnostic()?; - - // Deserialize the config and collect unused keys - let mut unused_keys = Set::new(); - let mut config: Config = serde_ignored::deserialize(de, |path| { - unused_keys.insert(path.to_string()); - }) - .into_diagnostic()?; + // Parse through the shared two-pass deserializer: keys are consumed + // by either the common configuration or the pixi extension; keys + // that neither recognizes (typos, keys of other tools) are returned + // so callers can warn about them. + let (inner, unused_keys) = + ConfigBase::::from_toml_str(toml).into_diagnostic()?; + let mut config = Config { inner }; fn create_deprecation_warning(old: &str, new: &str, source_path: Option<&Path>) { let msg = format!( @@ -1529,25 +1511,37 @@ impl Config { } } - if config.change_ps1.is_some() { + if config.extensions.change_ps1.is_some() { create_deprecation_warning("change-ps1", "shell.change-ps1", source_path); - config.shell.change_ps1 = config.change_ps1; + config.extensions.shell.change_ps1 = config.extensions.change_ps1; } - if config.force_activate.is_some() { + if config.extensions.force_activate.is_some() { create_deprecation_warning("force-activate", "shell.force-activate", source_path); - config.shell.force_activate = config.force_activate; + config.extensions.shell.force_activate = config.extensions.force_activate; } - warn_deprecated_tls_root_certs( - config.tls_root_certs, - source_path.map(|p| p.display().to_string()).as_deref(), - ); + // The shared `TlsRootCerts` deserializer accepts the legacy + // `"native"` / `"all"` spellings as silent aliases of `system`; + // inspect the raw document to keep pixi's deprecation warnings. + warn_deprecated_tls_root_certs_in_document(toml, source_path); + + // An explicitly empty channel list is treated the same as an absent + // one, preserving the merge semantics of the former `Config` (where + // the field was a plain `Vec` and empty meant "not set"). + if config + .common + .default_channels + .as_ref() + .is_some_and(Vec::is_empty) + { + config.common.default_channels = None; + } // Expand `~` in every [cache] path, matching how the top-level // `detached-environments` field is handled. Validation that the // expanded paths are absolute happens in `Config::validate`. - config.cache.expand_paths()?; + config.extensions.cache.expand_paths()?; Ok((config, unused_keys)) } @@ -1653,12 +1647,12 @@ impl Config { /// Validate the config file. pub fn validate(&self) -> miette::Result<()> { // Validate the detached environments directory is set correctly - if let Some(detached_environments) = self.detached_environments.as_ref() { + if let Some(detached_environments) = self.extensions.detached_environments.as_ref() { detached_environments.validate()? } // Validate that all configured [cache] paths are absolute. - self.cache.validate()?; + self.extensions.cache.validate()?; Ok(()) } @@ -1813,83 +1807,35 @@ impl Config { /// Merge the `other` config into `self`. /// The `other` config will have higher priority #[must_use] - pub fn merge_config(mut self, mut other: Config) -> Self { - // Brought in for the trait methods on rattler_config types - // (e.g. ConcurrencyConfig::merge_config). - use rattler_config::config::Config as _; - - self.mirrors.extend(other.mirrors); - other.loaded_from.extend(self.loaded_from); - - Self { - default_channels: if other.default_channels.is_empty() { - self.default_channels - } else { - other.default_channels - }, - tls_no_verify: other.tls_no_verify.or(self.tls_no_verify), - tls_root_certs: other.tls_root_certs.or(self.tls_root_certs), - authentication_override_file: other - .authentication_override_file - .or(self.authentication_override_file), - // Extended self.mirrors with other.mirrors - mirrors: self.mirrors, - loaded_from: other.loaded_from, - channel_config: if other.channel_config == default_channel_config() { - self.channel_config - } else { - other.channel_config - }, - repodata_config: self - .repodata_config - .merge_config(&other.repodata_config) - .expect("RepodataConfig::merge_config is infallible"), - pypi_config: self.pypi_config.merge(other.pypi_config), - s3_options: S3OptionsMap( - self.s3_options - .0 - .into_iter() - .chain(other.s3_options.0) - .collect(), - ), - detached_environments: other.detached_environments.or(self.detached_environments), - pinning_strategy: other.pinning_strategy.or(self.pinning_strategy), - shell: self.shell.merge(other.shell), - experimental: self.experimental.merge(other.experimental), - // Make other take precedence over self to allow for setting the value through the CLI - concurrency: self - .concurrency - .merge_config(&other.concurrency) - .expect("ConcurrencyConfig::merge_config is infallible"), - run_post_link_scripts: other.run_post_link_scripts.or(self.run_post_link_scripts), - allow_symbolic_links: other.allow_symbolic_links.or(self.allow_symbolic_links), - allow_hard_links: other.allow_hard_links.or(self.allow_hard_links), - allow_ref_links: other.allow_ref_links.or(self.allow_ref_links), - - proxy_config: self - .proxy_config - .merge_config(&other.proxy_config) - .expect("ProxyConfig::merge_config is infallible"), - build: self - .build - .merge_config(&other.build) - .expect("BuildConfig::merge_config is infallible"), - tool_platform: self.tool_platform.or(other.tool_platform), - cache: self.cache.merge(other.cache), + pub fn merge_config(self, other: Config) -> Self { + // The shared merge (`ConfigBase::merge_config`) handles both the + // common fields and the pixi extension (via `PixiConfig`'s + // `RattlerConfig` impl). The only pixi-specific deviation is the + // handling of the serde-skipped `channel_config`, which the shared + // merge always takes from `self`. + let self_channel_config = self.inner.common.channel_config.clone(); + let other_channel_config = other.inner.common.channel_config.clone(); + + let mut merged = self + .inner + .merge_config(&other.inner) + .expect("merging pixi configs is infallible"); + + merged.common.channel_config = if other_channel_config == default_channel_config() { + self_channel_config + } else { + other_channel_config + }; - // Deprecated fields that we can ignore as we handle them inside `shell.` field - change_ps1: None, - force_activate: None, - } + Config { inner: merged } } /// Retrieve the value for the default_channels field (defaults to the /// ["conda-forge"]). pub fn default_channels(&self) -> Vec { - if self.default_channels.is_empty() { - consts::DEFAULT_CHANNELS.clone() - } else { - self.default_channels.clone() + match &self.common.default_channels { + Some(channels) if !channels.is_empty() => channels.clone(), + _ => consts::DEFAULT_CHANNELS.clone(), } } @@ -1905,12 +1851,12 @@ impl Config { /// since the choice depends on whether pixi is built against `native-tls` /// or `rustls` and this crate is feature-agnostic. pub fn tls_root_certs(&self) -> Option { - self.tls_root_certs + self.common.tls_root_certs } /// Retrieve the value for the change_ps1 field (defaults to true). pub fn change_ps1(&self) -> bool { - self.shell.change_ps1.unwrap_or(true) + self.extensions.shell.change_ps1.unwrap_or(true) } /// Retrieve the value for the auth_file field. @@ -1932,31 +1878,56 @@ impl Config { } pub fn pypi_config(&self) -> &PyPIConfig { - &self.pypi_config + &self.extensions.pypi_config + } + + /// Shell-specific configuration. + pub fn shell(&self) -> &ShellConfig { + &self.extensions.shell } - pub fn mirror_map(&self) -> &std::collections::HashMap> { - &self.mirrors + /// Experimental features that can be enabled. + pub fn experimental(&self) -> &ExperimentalConfig { + &self.extensions.experimental + } + + /// Per-cache directory configuration. + pub fn cache(&self) -> &CacheConfig { + &self.extensions.cache + } + + /// Dependency pinning strategy used by e.g. `pixi add`, if configured. + pub fn pinning_strategy(&self) -> Option { + self.extensions.pinning_strategy + } + + pub fn mirror_map(&self) -> &IndexMap> { + &self.common.mirrors } /// Retrieve the value for the target_environments_directory field. pub fn detached_environments(&self) -> DetachedEnvironments { - self.detached_environments.clone().unwrap_or_default() + self.extensions + .detached_environments + .clone() + .unwrap_or_default() } /// Resolve the detached-environments directory for this config, honoring /// this config's `[cache]` settings when the directory has to be derived. /// Returns `None` when detached-environments is disabled. pub fn detached_environments_dir(&self) -> miette::Result> { - self.detached_environments().path(&self.cache) + self.detached_environments().path(&self.extensions.cache) } pub fn force_activate(&self) -> bool { - self.shell.force_activate.unwrap_or(false) + self.extensions.shell.force_activate.unwrap_or(false) } pub fn experimental_activation_cache_usage(&self) -> bool { - self.experimental.use_environment_activation_cache() + self.extensions + .experimental + .use_environment_activation_cache() } /// Retrieve the value for the max_concurrent_solves field. @@ -1971,7 +1942,7 @@ impl Config { /// The platform to use to install tools. pub fn tool_platform(&self) -> Platform { - self.tool_platform.unwrap_or(Platform::current()) + self.extensions.tool_platform.unwrap_or(Platform::current()) } pub fn get_proxies(&self) -> reqwest::Result> { @@ -2013,47 +1984,34 @@ impl Config { /// Modify this config with the given key and value /// + /// Keys are dotted TOML paths (`concurrency.solves`, + /// `s3-options.my-bucket.region`). Everything except a handful of + /// pixi-specific special cases is handled by the generic + /// [`ConfigBase::set`], which works for both the shared keys and the + /// pixi extension keys. + /// /// # Note /// /// It is required to call `save()` to persist the changes. pub fn set(&mut self, key: &str, value: Option) -> miette::Result<()> { - let show_supported_keys = - || format!("Supported keys:\n\t{}", self.get_keys().join(",\n\t")); - let err = miette::miette!( - "Unknown key: {}\n{}", - console::style(key).red(), - show_supported_keys() - ); - match key { - "default-channels" => { - self.default_channels = value - .map(|v| serde_json::de::from_str(&v)) - .transpose() - .into_diagnostic()? - .unwrap_or_default(); - } - "authentication-override-file" => { - self.authentication_override_file = value.map(PathBuf::from); - } - "tls-no-verify" => { - self.tls_no_verify = value.map(|v| v.parse()).transpose().into_diagnostic()?; - } - "tls-root-certs" => { - self.tls_root_certs = value - .map(|v| TlsRootCerts::from_str(v.as_str())) - .transpose() - .into_diagnostic()?; + // Deprecated top-level keys are rejected with a pointer to their + // `shell.*` replacements (the extension still deserializes them + // from files for backwards compatibility). + "change-ps1" => { + return Err(miette::miette!( + "The `change-ps1` field is deprecated. Please use the `shell.change-ps1` field instead." + )); } - "mirrors" => { - self.mirrors = value - .map(|v| serde_json::de::from_str(&v)) - .transpose() - .into_diagnostic()? - .unwrap_or_default(); + "force-activate" => { + return Err(miette::miette!( + "The `force-activate` field is deprecated. Please use the `shell.force-activate` field instead." + )); } + // `detached-environments` accepts booleans and paths; paths get + // `~` expanded, which the generic editor knows nothing about. "detached-environments" => { - self.detached_environments = value + self.inner.extensions.detached_environments = value .map(|v| { Ok::<_, miette::Report>(match v.as_str() { "true" => DetachedEnvironments::Boolean(true), @@ -2063,339 +2021,17 @@ impl Config { }) .transpose()?; } - "pinning-strategy" => { - self.pinning_strategy = value - .map(|v| PinningStrategy::from_str(v.as_str())) - .transpose() - .into_diagnostic()? - } - "change-ps1" => { - return Err(miette::miette!( - "The `change-ps1` field is deprecated. Please use the `shell.change-ps1` field instead." - )); - } - "force-activate" => { - return Err(miette::miette!( - "The `force-activate` field is deprecated. Please use the `shell.force-activate` field instead." - )); - } - "tool-platform" => { - self.tool_platform = value - .as_deref() - .map(Platform::from_str) - .transpose() - .into_diagnostic()?; - } - key if key.starts_with("repodata-config") => { - if key == "repodata-config" { - self.repodata_config = value - .map(|v| serde_json::de::from_str(&v)) - .transpose() - .into_diagnostic()? - .unwrap_or_default(); - return Ok(()); - } else if !key.starts_with("repodata-config.") { - return Err(err); - } - - let subkey = key.strip_prefix("repodata-config.").unwrap(); - match subkey { - "disable-bzip2" => { - self.repodata_config.default.disable_bzip2 = - value.map(|v| v.parse()).transpose().into_diagnostic()?; - } - "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), - } - } - key if key.starts_with("pypi-config") => { - if key == "pypi-config" { - if let Some(value) = value { - self.pypi_config = serde_json::de::from_str(&value).into_diagnostic()?; - } else { - self.pypi_config = PyPIConfig::default(); - } - return Ok(()); - } else if !key.starts_with("pypi-config.") { - return Err(err); - } - - let subkey = key.strip_prefix("pypi-config.").unwrap(); - match subkey { - "index-url" => { - self.pypi_config.index_url = value - .map(|v| Url::parse(&v)) - .transpose() - .into_diagnostic()?; - } - "extra-index-urls" => { - self.pypi_config.extra_index_urls = value - .map(|v| serde_json::de::from_str(&v)) - .transpose() - .into_diagnostic()? - .unwrap_or_default(); - } - "keyring-provider" => { - self.pypi_config.keyring_provider = value - .map(|v| match v.as_str() { - "disabled" => Ok(KeyringProvider::Disabled), - "subprocess" => Ok(KeyringProvider::Subprocess), - _ => Err(miette::miette!("invalid keyring provider")), - }) - .transpose()?; - } - "allow-insecure-host" => { - self.pypi_config.allow_insecure_host = value - .map(|v| serde_json::de::from_str(&v)) - .transpose() - .into_diagnostic()? - .unwrap_or_default(); - } - _ => return Err(err), - } - } - key if key.starts_with("s3-options") => { - if key == "s3-options" { - if let Some(value) = value { - self.s3_options = serde_json::de::from_str(&value).into_diagnostic()?; - } else { - return Err(miette!("s3-options requires a value")); - } - return Ok(()); - } - let Some(subkey) = key.strip_prefix("s3-options.") else { - return Err(err); - }; - if let Some((bucket, rest)) = subkey.split_once('.') { - if let Some(bucket_config) = self.s3_options.0.get_mut(bucket) { - match rest { - "endpoint-url" => { - if let Some(value) = value { - bucket_config.endpoint_url = - Url::parse(&value).into_diagnostic()?; - } else { - return Err(miette!( - "s3-options.{}.endpoint-url requires a value", - bucket - )); - } - } - "region" => { - if let Some(value) = value { - bucket_config.region = value; - } else { - return Err(miette!( - "s3-options.{}.region requires a value", - bucket - )); - } - } - "force-path-style" => { - if let Some(value) = value { - bucket_config.force_path_style = - value.parse().into_diagnostic()?; - } else { - return Err(miette!( - "s3-options.{}.force-path-style requires a value", - bucket - )); - } - } - _ => return Err(err), - } - } - } else { - let value = value.ok_or_else(|| miette!("s3-options requires a value"))?; - let s3_options: S3Options = - serde_json::de::from_str(&value).into_diagnostic()?; - self.s3_options.0.insert(subkey.to_string(), s3_options); - } - } - key if key.starts_with(EXPERIMENTAL) => { - if key == EXPERIMENTAL { - if let Some(value) = value { - self.experimental = serde_json::de::from_str(&value).into_diagnostic()?; - } else { - self.experimental = ExperimentalConfig::default(); - } - return Ok(()); - } else if !key.starts_with(format!("{EXPERIMENTAL}.").as_str()) { - return Err(err); - } - - let subkey = key - .strip_prefix(format!("{EXPERIMENTAL}.").as_str()) - .unwrap(); - match subkey { - "use-environment-activation-cache" => { - self.experimental.use_environment_activation_cache = - value.map(|v| v.parse()).transpose().into_diagnostic()?; - } - _ => return Err(err), - } - } - key if key.starts_with("concurrency") => { - if key == "concurrency" { - if let Some(value) = value { - self.pypi_config = serde_json::de::from_str(&value).into_diagnostic()?; - } else { - self.pypi_config = PyPIConfig::default(); - } - return Ok(()); - } else if !key.starts_with("concurrency.") { - return Err(err); - } - let subkey = key.strip_prefix("concurrency.").unwrap(); - match subkey { - "solves" => { - if let Some(value) = value { - self.concurrency.solves = value.parse().into_diagnostic()?; - } else { - return Err(miette!("'solves' requires a number value")); - } - } - "downloads" => { - if let Some(value) = value { - self.concurrency.downloads = value.parse().into_diagnostic()?; - } else { - return Err(miette!("'downloads' requires a number value")); - } - } - _ => return Err(err), - } - } - key if key.starts_with("shell") => { - if key == "shell" { - if let Some(value) = value { - self.shell = serde_json::de::from_str(&value).into_diagnostic()?; - } else { - self.shell = ShellConfig::default(); - } - return Ok(()); - } else if !key.starts_with("shell.") { - return Err(err); - } - let subkey = key.strip_prefix("shell.").unwrap(); - match subkey { - "force-activate" => { - self.shell.force_activate = - value.map(|v| v.parse()).transpose().into_diagnostic()?; - } - "source-completion-scripts" => { - self.shell.source_completion_scripts = - value.map(|v| v.parse()).transpose().into_diagnostic()?; - } - "change-ps1" => { - self.shell.change_ps1 = - value.map(|v| v.parse()).transpose().into_diagnostic()?; - } - _ => return Err(err), - } - } - key if key.starts_with("run-post-link-scripts") => { - if let Some(value) = value { - self.run_post_link_scripts = Some( - value - .parse() - .into_diagnostic() - .wrap_err("failed to parse run-post-link-scripts")?, - ); - } - return Ok(()); - } - "allow-symbolic-links" => { - self.allow_symbolic_links = - value.map(|v| v.parse()).transpose().into_diagnostic()?; - } - "allow-hard-links" => { - self.allow_hard_links = value.map(|v| v.parse()).transpose().into_diagnostic()?; - } - "allow-ref-links" => { - self.allow_ref_links = value.map(|v| v.parse()).transpose().into_diagnostic()?; - } - key if key.starts_with("proxy-config") => { - if key == "proxy-config" { - if let Some(value) = value { - self.proxy_config = serde_json::de::from_str(&value).into_diagnostic()?; - } else { - self.proxy_config = ProxyConfig::default(); - } - return Ok(()); - } else if !key.starts_with("proxy-config.") { - return Err(err); - } - - let subkey = key.strip_prefix("proxy-config.").unwrap(); - match subkey { - "https" => { - self.proxy_config.https = value - .map(|v| Url::parse(&v)) - .transpose() - .into_diagnostic()?; - } - "http" => { - self.proxy_config.http = value - .map(|v| Url::parse(&v)) - .transpose() - .into_diagnostic()?; - } - "non-proxy-hosts" => { - self.proxy_config.non_proxy_hosts = value - .map(|v| serde_json::de::from_str(&v)) - .transpose() - .into_diagnostic()? - .unwrap_or_default(); - } - _ => return Err(err), - } - } - key if key.starts_with("cache") => { - if key == "cache" { - if let Some(value) = value { - self.cache = serde_json::de::from_str(&value).into_diagnostic()?; - } else { - self.cache = CacheConfig::default(); - } - self.cache.expand_paths()?; - self.cache.validate()?; - return Ok(()); - } else if !key.starts_with("cache.") { - return Err(err); + // Everything else goes through the shared generic editor. + _ => { + self.inner.set(key, value).into_diagnostic()?; + + // `[cache]` paths support `~` and must be absolute; re-run + // the same post-processing as `Config::from_toml`. + if key == "cache" || key.starts_with("cache.") { + self.inner.extensions.cache.expand_paths()?; + self.inner.extensions.cache.validate()?; } - let subkey = key.strip_prefix("cache.").unwrap(); - match subkey { - "root" => self.cache.root = value.map(PathBuf::from), - "conda-packages" => self.cache.conda_packages = value.map(PathBuf::from), - "repodata" => self.cache.repodata = value.map(PathBuf::from), - "pypi-wheels" => self.cache.pypi_wheels = value.map(PathBuf::from), - "pypi-mapping" => self.cache.pypi_mapping = value.map(PathBuf::from), - "exec-environments" => self.cache.exec_environments = value.map(PathBuf::from), - "build-tool-environments" => { - self.cache.build_tool_environments = value.map(PathBuf::from) - } - "detached-environments" => { - self.cache.detached_environments = value.map(PathBuf::from) - } - "netfs-redirect" => { - self.cache.netfs_redirect = value - .map(|v| NetfsRedirect::from_str(&v)) - .transpose() - .into_diagnostic()? - .unwrap_or_default(); - } - _ => return Err(err), - } - self.cache.expand_paths()?; - self.cache.validate()?; } - _ => return Err(err), } Ok(()) @@ -2421,7 +2057,7 @@ impl Config { /// Resolve the cache directory for `kind`, applying this config's /// `[cache]` settings on top of the env-var / default resolution. pub fn cache_dir_for(&self, kind: CacheKind) -> miette::Result { - resolve_cache_kind_dir(&self.cache, kind) + resolve_cache_kind_dir(&self.extensions.cache, kind) } /// Constructs a [`GatewayBuilder`] with preconfigured settings. @@ -2499,6 +2135,13 @@ mod tests { use super::*; + /// Test helper: a default `Config` with the given `[cache]` section. + fn config_with_cache(cache: CacheConfig) -> Config { + let mut config = Config::default(); + config.extensions.cache = cache; + config + } + #[test] fn test_config_parse() { // Calls get_cache_dir() via detached_environments_dir(); serialize @@ -2518,12 +2161,12 @@ UNUSED = "unused" let (config, unused) = Config::from_toml(toml.as_str(), None).unwrap(); assert_eq!( config.default_channels, - vec![NamedChannelOrUrl::from_str("conda-forge").unwrap()] + Some(vec![NamedChannelOrUrl::from_str("conda-forge").unwrap()]) ); assert_eq!(config.tls_no_verify, Some(true)); - #[allow(deprecated)] - let expected_legacy = TlsRootCerts::LegacyNative; - assert_eq!(config.tls_root_certs, Some(expected_legacy)); + // The legacy `"native"` spelling deserializes as an alias of + // `System` (a load-time deprecation warning still fires). + assert_eq!(config.tls_root_certs, Some(TlsRootCerts::System)); assert_eq!( config.detached_environments_dir().unwrap(), Some(PathBuf::from(env!("CARGO_MANIFEST_DIR"))) @@ -2552,7 +2195,7 @@ UNUSED = "unused" fn test_config_parse_pinning_strategy(#[case] input: &str, #[case] expected: PinningStrategy) { let toml = format!("pinning-strategy = \"{input}\""); let (config, _) = Config::from_toml(&toml, None).unwrap(); - assert_eq!(config.pinning_strategy, Some(expected)); + assert_eq!(config.pinning_strategy(), Some(expected)); } /// Assert that usage of `~` in `detached_environments` is correctly expanded @@ -2640,10 +2283,10 @@ UNUSED = "unused" Some(RunPostLinkScripts::Insecure) ); assert_eq!( - config.experimental.use_environment_activation_cache, + config.experimental().use_environment_activation_cache, Some(true) ); - assert_eq!(config.pinning_strategy, Some(PinningStrategy::Semver)); + assert_eq!(config.pinning_strategy(), Some(PinningStrategy::Semver)); let cli = ConfigCli { tls_no_verify: false, @@ -2668,8 +2311,8 @@ UNUSED = "unused" Some(PathBuf::from("path.json")) ); assert_eq!(config.run_post_link_scripts, None); - assert_eq!(config.experimental.use_environment_activation_cache, None); - assert_eq!(config.pinning_strategy, None); + assert_eq!(config.experimental().use_environment_activation_cache, None); + assert_eq!(config.pinning_strategy(), None); } #[test] @@ -2717,7 +2360,7 @@ UNUSED = "unused" force-path-style = false "#; let (config, _) = Config::from_toml(toml, None).unwrap(); - let s3_options = config.s3_options.0; + let s3_options = &config.s3_options.0; assert_eq!( s3_options["bucket1"].endpoint_url, Url::parse("https://my-s3-host").unwrap() @@ -2757,76 +2400,84 @@ UNUSED = "unused" fn test_config_merge_priority() { // If I set every config key, ensure that `other wins` let mut config = Config::default(); - let other = Config { - default_channels: vec![NamedChannelOrUrl::from_str("conda-forge").unwrap()], - channel_config: ChannelConfig::default_with_root_dir(PathBuf::from("/root/dir")), - tls_no_verify: Some(true), - tls_root_certs: Some(TlsRootCerts::System), - detached_environments: Some(DetachedEnvironments::Path(PathBuf::from("/path/to/envs"))), - concurrency: ConcurrencyConfig { - solves: 5, - ..ConcurrencyConfig::default() - }, - authentication_override_file: Some(PathBuf::default()), - mirrors: HashMap::from([( - Url::parse("https://conda.anaconda.org/conda-forge").unwrap(), - Vec::default(), - )]), - pinning_strategy: Some(PinningStrategy::NoPin), - experimental: ExperimentalConfig { - use_environment_activation_cache: Some(true), - }, - loaded_from: Vec::from([PathBuf::from_str("test").unwrap()]), - shell: ShellConfig { - force_activate: Some(true), - source_completion_scripts: None, - change_ps1: Some(false), - }, - pypi_config: PyPIConfig { - allow_insecure_host: Vec::from(["test".to_string()]), - extra_index_urls: Vec::from([ - Url::parse("https://conda.anaconda.org/conda-forge").unwrap() - ]), - index_url: Some(Url::parse("https://conda.anaconda.org/conda-forge").unwrap()), - keyring_provider: Some(KeyringProvider::Subprocess), - }, - s3_options: S3OptionsMap(IndexMap::from([( - "bucket1".into(), - S3Options { - endpoint_url: Url::parse("https://my-s3-host").unwrap(), - region: "us-east-1".to_string(), - force_path_style: false, + let other = Config::from(ConfigBase { + common: CommonConfig { + default_channels: Some(vec![NamedChannelOrUrl::from_str("conda-forge").unwrap()]), + channel_config: ChannelConfig::default_with_root_dir(PathBuf::from("/root/dir")), + tls_no_verify: Some(true), + tls_root_certs: Some(TlsRootCerts::System), + concurrency: ConcurrencyConfig { + solves: 5, + ..ConcurrencyConfig::default() }, - )])), - repodata_config: RepodataConfig { - default: RepodataChannelConfig { - disable_bzip2: Some(true), - disable_sharded: Some(true), - disable_zstd: Some(true), - }, - per_channel: HashMap::from([( + authentication_override_file: Some(PathBuf::default()), + mirrors: IndexMap::from([( Url::parse("https://conda.anaconda.org/conda-forge").unwrap(), - RepodataChannelConfig::default(), + Vec::default(), )]), + s3_options: S3OptionsMap(IndexMap::from([( + "bucket1".into(), + S3Options { + endpoint_url: Url::parse("https://my-s3-host").unwrap(), + region: "us-east-1".to_string(), + force_path_style: false, + }, + )])), + repodata_config: RepodataConfig { + default: RepodataChannelConfig { + disable_bzip2: Some(true), + disable_sharded: Some(true), + disable_zstd: Some(true), + }, + per_channel: HashMap::from([( + Url::parse("https://conda.anaconda.org/conda-forge").unwrap(), + RepodataChannelConfig::default(), + )]), + }, + run_post_link_scripts: Some(RunPostLinkScripts::Insecure), + allow_symbolic_links: Some(true), + allow_hard_links: Some(true), + allow_ref_links: Some(false), + proxy_config: ProxyConfig::default(), + build: BuildConfig::default(), + ..CommonConfig::default() }, - run_post_link_scripts: Some(RunPostLinkScripts::Insecure), - allow_symbolic_links: Some(true), - allow_hard_links: Some(true), - allow_ref_links: Some(false), - proxy_config: ProxyConfig::default(), - build: BuildConfig::default(), - tool_platform: None, - cache: CacheConfig { - root: Some(PathBuf::from("/some/cache/root")), - conda_packages: Some(PathBuf::from("/shared/pkgs")), - pypi_mapping: Some(PathBuf::from("/local/mapping")), - netfs_redirect: NetfsRedirect::Always, - ..CacheConfig::default() + extensions: PixiConfig { + detached_environments: Some(DetachedEnvironments::Path(PathBuf::from( + "/path/to/envs", + ))), + pinning_strategy: Some(PinningStrategy::NoPin), + experimental: ExperimentalConfig { + use_environment_activation_cache: Some(true), + }, + shell: ShellConfig { + force_activate: Some(true), + source_completion_scripts: None, + change_ps1: Some(false), + }, + pypi_config: PyPIConfig { + allow_insecure_host: Vec::from(["test".to_string()]), + extra_index_urls: Vec::from([Url::parse( + "https://conda.anaconda.org/conda-forge", + ) + .unwrap()]), + index_url: Some(Url::parse("https://conda.anaconda.org/conda-forge").unwrap()), + keyring_provider: Some(KeyringProvider::Subprocess), + }, + tool_platform: None, + cache: CacheConfig { + root: Some(PathBuf::from("/some/cache/root")), + conda_packages: Some(PathBuf::from("/shared/pkgs")), + pypi_mapping: Some(PathBuf::from("/local/mapping")), + netfs_redirect: NetfsRedirect::Always, + ..CacheConfig::default() + }, + // Deprecated keys + change_ps1: None, + force_activate: None, }, - // Deprecated keys - change_ps1: None, - force_activate: None, - }; + loaded_from: Vec::from([PathBuf::from_str("test").unwrap()]), + }); let original_other = other.clone(); config = config.merge_config(other); assert_eq!(config, original_other); @@ -2834,39 +2485,47 @@ UNUSED = "unused" #[test] fn test_config_merge_multiple() { let mut config = Config::default(); - let other = Config { - default_channels: vec![NamedChannelOrUrl::from_str("conda-forge").unwrap()], - channel_config: ChannelConfig::default_with_root_dir(PathBuf::from("/root/dir")), - tls_no_verify: Some(true), - detached_environments: Some(DetachedEnvironments::Path(PathBuf::from("/path/to/envs"))), - concurrency: ConcurrencyConfig { - solves: 5, - ..ConcurrencyConfig::default() + let other = Config::from(ConfigBase { + common: CommonConfig { + default_channels: Some(vec![NamedChannelOrUrl::from_str("conda-forge").unwrap()]), + channel_config: ChannelConfig::default_with_root_dir(PathBuf::from("/root/dir")), + tls_no_verify: Some(true), + concurrency: ConcurrencyConfig { + solves: 5, + ..ConcurrencyConfig::default() + }, + s3_options: S3OptionsMap(IndexMap::from([ + ( + "bucket1".into(), + S3Options { + endpoint_url: Url::parse("https://my-s3-host").unwrap(), + region: "us-east-1".to_string(), + force_path_style: false, + }, + ), + ( + "bucket2".into(), + S3Options { + endpoint_url: Url::parse("https://my-s3-host").unwrap(), + region: "us-east-1".to_string(), + force_path_style: false, + }, + ), + ])), + ..CommonConfig::default() }, - s3_options: S3OptionsMap(IndexMap::from([ - ( - "bucket1".into(), - S3Options { - endpoint_url: Url::parse("https://my-s3-host").unwrap(), - region: "us-east-1".to_string(), - force_path_style: false, - }, - ), - ( - "bucket2".into(), - S3Options { - endpoint_url: Url::parse("https://my-s3-host").unwrap(), - region: "us-east-1".to_string(), - force_path_style: false, - }, - ), - ])), - ..Default::default() - }; + extensions: PixiConfig { + detached_environments: Some(DetachedEnvironments::Path(PathBuf::from( + "/path/to/envs", + ))), + ..PixiConfig::default() + }, + loaded_from: Vec::new(), + }); config = config.merge_config(other); assert_eq!( config.default_channels, - vec![NamedChannelOrUrl::from_str("conda-forge").unwrap()] + Some(vec![NamedChannelOrUrl::from_str("conda-forge").unwrap()]) ); assert_eq!(config.tls_no_verify, Some(true)); assert_eq!( @@ -2875,28 +2534,34 @@ UNUSED = "unused" ); assert!(config.s3_options.0.contains_key("bucket1")); - let other2 = Config { - default_channels: vec![NamedChannelOrUrl::from_str("channel").unwrap()], - channel_config: ChannelConfig::default_with_root_dir(PathBuf::from("/root/dir2")), - tls_no_verify: Some(false), - detached_environments: Some(DetachedEnvironments::Path(PathBuf::from( - "/path/to/envs2", - ))), - s3_options: S3OptionsMap(IndexMap::from([( - "bucket2".into(), - S3Options { - endpoint_url: Url::parse("https://my-new-s3-host").unwrap(), - region: "us-east-1".to_string(), - force_path_style: false, - }, - )])), - ..Default::default() - }; + let other2 = Config::from(ConfigBase { + common: CommonConfig { + default_channels: Some(vec![NamedChannelOrUrl::from_str("channel").unwrap()]), + channel_config: ChannelConfig::default_with_root_dir(PathBuf::from("/root/dir2")), + tls_no_verify: Some(false), + s3_options: S3OptionsMap(IndexMap::from([( + "bucket2".into(), + S3Options { + endpoint_url: Url::parse("https://my-new-s3-host").unwrap(), + region: "us-east-1".to_string(), + force_path_style: false, + }, + )])), + ..CommonConfig::default() + }, + extensions: PixiConfig { + detached_environments: Some(DetachedEnvironments::Path(PathBuf::from( + "/path/to/envs2", + ))), + ..PixiConfig::default() + }, + loaded_from: Vec::new(), + }); config = config.merge_config(other2); assert_eq!( config.default_channels, - vec![NamedChannelOrUrl::from_str("channel").unwrap()] + Some(vec![NamedChannelOrUrl::from_str("channel").unwrap()]) ); assert_eq!(config.tls_no_verify, Some(false)); assert_eq!( @@ -2918,12 +2583,10 @@ UNUSED = "unused" .join("config"); let config_1 = Config::from_path(&d.join("config_1.toml")).unwrap(); - let config_2 = Config::from_path(&d.join("config_2.toml")).unwrap(); - let config_2 = Config { - channel_config: ChannelConfig::default_with_root_dir(PathBuf::from("/root/dir")), - detached_environments: Some(DetachedEnvironments::Boolean(true)), - ..config_2 - }; + let mut config_2 = Config::from_path(&d.join("config_2.toml")).unwrap(); + config_2.common.channel_config = + ChannelConfig::default_with_root_dir(PathBuf::from("/root/dir")); + config_2.extensions.detached_environments = Some(DetachedEnvironments::Boolean(true)); let mut merged = config_1.clone(); merged = merged.merge_config(config_2); @@ -2954,21 +2617,21 @@ UNUSED = "unused" let (config, _) = Config::from_toml(toml, None).unwrap(); assert_eq!( config.default_channels, - vec![NamedChannelOrUrl::from_str("conda-forge").unwrap()] + Some(vec![NamedChannelOrUrl::from_str("conda-forge").unwrap()]) ); assert_eq!(config.tls_no_verify, Some(false)); assert_eq!( config.authentication_override_file, Some(PathBuf::from("/path/to/your/override.json")) ); - assert_eq!(config.change_ps1, Some(true)); + assert_eq!(config.extensions.change_ps1, Some(true)); assert_eq!( config .mirrors .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; + let repodata_config = &config.repodata_config; 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); @@ -3002,7 +2665,7 @@ UNUSED = "unused" .unwrap(); assert_eq!( config.default_channels, - vec![NamedChannelOrUrl::from_str("conda-forge").unwrap()] + Some(vec![NamedChannelOrUrl::from_str("conda-forge").unwrap()]) ); config @@ -3085,7 +2748,7 @@ UNUSED = "unused" assert!(deprecated.unwrap_err().to_string().contains("deprecated")); config.set("shell.change-ps1", None).unwrap(); - assert_eq!(config.change_ps1, None); + assert_eq!(config.extensions.change_ps1, None); config .set("concurrency.solves", Some("10".to_string())) @@ -3120,7 +2783,7 @@ UNUSED = "unused" config .set("tool-platform", Some("linux-64".to_string())) .unwrap(); - assert_eq!(config.tool_platform, Some(Platform::Linux64)); + assert_eq!(config.extensions.tool_platform, Some(Platform::Linux64)); // Test run-post-link-scripts config @@ -3135,13 +2798,16 @@ UNUSED = "unused" config .set("shell.force-activate", Some("true".to_string())) .unwrap(); - assert_eq!(config.shell.force_activate, Some(true)); + assert_eq!(config.extensions.shell.force_activate, Some(true)); // Test shell.source-completion-scripts config .set("shell.source-completion-scripts", Some("false".to_string())) .unwrap(); - assert_eq!(config.shell.source_completion_scripts, Some(false)); + assert_eq!( + config.extensions.shell.source_completion_scripts, + Some(false) + ); // Test experimental.use-environment-activation-cache config @@ -3151,7 +2817,10 @@ UNUSED = "unused" ) .unwrap(); assert_eq!( - config.experimental.use_environment_activation_cache, + config + .extensions + .experimental + .use_environment_activation_cache, Some(true) ); @@ -3221,7 +2890,20 @@ UNUSED = "unused" .unwrap(); assert_eq!(config.proxy_config.non_proxy_hosts.len(), 2); - // Test s3-options with individual keys + // Test s3-options with individual keys. The bucket has to exist + // before its individual fields can be edited: a partial bucket + // table is rejected (`S3Options` requires all three fields). + // Note: editing a *non-existent* bucket's subkey used to be a + // silent no-op; with the generic editor it is now a proper error. + assert!( + config + .set( + "s3-options.absent-bucket.region", + Some("us-east-1".to_string()), + ) + .is_err() + ); + config.set("s3-options.test-bucket", Some(r#"{"endpoint-url": "http://localhost:2222", "force-path-style": true, "region": "eu-west-1"}"#.to_string())).unwrap(); config .set( "s3-options.test-bucket.endpoint-url", @@ -3240,6 +2922,13 @@ UNUSED = "unused" Some("false".to_string()), ) .unwrap(); + let test_bucket = &config.s3_options.0["test-bucket"]; + assert_eq!( + test_bucket.endpoint_url, + Url::parse("http://localhost:9000").unwrap() + ); + assert_eq!(test_bucket.region, "us-east-1"); + assert!(!test_bucket.force_path_style); // Test concurrency configuration config @@ -3268,13 +2957,12 @@ UNUSED = "unused" .unwrap(); assert_eq!(config.tls_root_certs, Some(TlsRootCerts::System)); - // The deprecated `native` spelling still deserializes. + // The deprecated `native` spelling still deserializes (as an alias + // of `System`). config .set("tls-root-certs", Some("native".to_string())) .unwrap(); - #[allow(deprecated)] - let expected_legacy = TlsRootCerts::LegacyNative; - assert_eq!(config.tls_root_certs, Some(expected_legacy)); + assert_eq!(config.tls_root_certs, Some(TlsRootCerts::System)); // Test mirrors config @@ -3290,7 +2978,7 @@ UNUSED = "unused" .set("detached-environments", Some("/custom/path".to_string())) .unwrap(); assert!(matches!( - config.detached_environments, + config.extensions.detached_environments, Some(DetachedEnvironments::Path(_)) )); @@ -3298,7 +2986,10 @@ UNUSED = "unused" config .set("pinning-strategy", Some("semver".to_string())) .unwrap(); - assert_eq!(config.pinning_strategy, Some(PinningStrategy::Semver)); + assert_eq!( + config.extensions.pinning_strategy, + Some(PinningStrategy::Semver) + ); config.set("unknown-key", None).unwrap_err(); } @@ -3318,7 +3009,7 @@ UNUSED = "unused" ) { let mut config = Config::default(); config.set(key, value).unwrap(); - assert_eq!(config.pinning_strategy, expected); + assert_eq!(config.extensions.pinning_strategy, expected); } #[test] @@ -3630,14 +3321,11 @@ UNUSED = "unused" // the per-kind [cache.pypi-mapping] path should override. let _force = ScopedEnv::set("PIXI_FORCE_NETFS_REDIRECT", "1"); - let config = Config { - cache: CacheConfig { - root: Some(PathBuf::from("/some/configured/root")), - pypi_mapping: Some(PathBuf::from("/explicit/per/kind/path")), - ..CacheConfig::default() - }, - ..Config::default() - }; + let config = config_with_cache(CacheConfig { + root: Some(PathBuf::from("/some/configured/root")), + pypi_mapping: Some(PathBuf::from("/explicit/per/kind/path")), + ..CacheConfig::default() + }); let got = config.cache_dir_for(CacheKind::PypiMapping).unwrap(); assert_eq!(got, PathBuf::from("/explicit/per/kind/path")); @@ -3658,13 +3346,10 @@ UNUSED = "unused" // The global (system + user) layer has no per-kind override. let global = Config::default(); // The workspace `.pixi/config.toml` sets the mapping cache path. - let workspace = Config { - cache: CacheConfig { - pypi_mapping: Some(PathBuf::from("/workspace/conda-pypi-mapping")), - ..CacheConfig::default() - }, - ..Config::default() - }; + let workspace = config_with_cache(CacheConfig { + pypi_mapping: Some(PathBuf::from("/workspace/conda-pypi-mapping")), + ..CacheConfig::default() + }); // `merge_config` mirrors how the workspace config is layered onto the // global config; this merged `Config` is what the mapping client now @@ -3688,13 +3373,10 @@ UNUSED = "unused" // [cache.root] in config should behave like a user pin: no redirect // even with FORCE_NETFS_REDIRECT, because the user explicitly chose // this location. - let config = Config { - cache: CacheConfig { - root: Some(PathBuf::from("/configured/root")), - ..CacheConfig::default() - }, - ..Config::default() - }; + let config = config_with_cache(CacheConfig { + root: Some(PathBuf::from("/configured/root")), + ..CacheConfig::default() + }); let got = config.cache_dir_for(CacheKind::PypiMapping).unwrap(); assert_eq!(got, PathBuf::from("/configured/root/conda-pypi-mapping")); @@ -3708,13 +3390,10 @@ UNUSED = "unused" let _rattler = ScopedEnv::unset("RATTLER_CACHE_DIR"); let _disable = ScopedEnv::unset("PIXI_DISABLE_NETFS_REDIRECT"); - let config = Config { - cache: CacheConfig { - netfs_redirect: NetfsRedirect::Never, - ..CacheConfig::default() - }, - ..Config::default() - }; + let config = config_with_cache(CacheConfig { + netfs_redirect: NetfsRedirect::Never, + ..CacheConfig::default() + }); let got = config.cache_dir_for(CacheKind::PypiMapping).unwrap(); assert!(!got.starts_with(node_local_scratch_dir())); @@ -3730,16 +3409,19 @@ UNUSED = "unused" netfs-redirect = "never" "#; let (config, _) = Config::from_toml(toml, None).unwrap(); - assert_eq!(config.cache.root, Some(PathBuf::from("/shared/hpc"))); assert_eq!( - config.cache.conda_packages, + config.extensions.cache.root, + Some(PathBuf::from("/shared/hpc")) + ); + assert_eq!( + config.extensions.cache.conda_packages, Some(PathBuf::from("/shared/hpc/pkgs")) ); assert_eq!( - config.cache.pypi_mapping, + config.extensions.cache.pypi_mapping, Some(PathBuf::from("/local/scratch/mapping")) ); - assert_eq!(config.cache.netfs_redirect, NetfsRedirect::Never); + assert_eq!(config.extensions.cache.netfs_redirect, NetfsRedirect::Never); } #[test] @@ -3751,9 +3433,12 @@ UNUSED = "unused" pypi-mapping = "~/scratch/mapping" "#; let (config, _) = Config::from_toml(toml, None).unwrap(); - assert_eq!(config.cache.root, Some(home_dir.join(".cache/pixi"))); assert_eq!( - config.cache.pypi_mapping, + config.extensions.cache.root, + Some(home_dir.join(".cache/pixi")) + ); + assert_eq!( + config.extensions.cache.pypi_mapping, Some(home_dir.join("scratch/mapping")) ); } @@ -3791,13 +3476,10 @@ UNUSED = "unused" let _disable = ScopedEnv::unset("PIXI_DISABLE_NETFS_REDIRECT"); let _env = ScopedEnv::set("PIXI_CACHE_PYPI_MAPPING_DIR", "/from/env/mapping"); - let config = Config { - cache: CacheConfig { - pypi_mapping: Some(PathBuf::from("/from/toml/mapping")), - ..CacheConfig::default() - }, - ..Config::default() - }; + let config = config_with_cache(CacheConfig { + pypi_mapping: Some(PathBuf::from("/from/toml/mapping")), + ..CacheConfig::default() + }); let got = config.cache_dir_for(CacheKind::PypiMapping).unwrap(); assert_eq!(got, PathBuf::from("/from/env/mapping")); @@ -3836,13 +3518,10 @@ UNUSED = "unused" let _disable = ScopedEnv::unset("PIXI_DISABLE_NETFS_REDIRECT"); let _redirect = ScopedEnv::set("PIXI_CACHE_NETFS_REDIRECT", "never"); - let config = Config { - cache: CacheConfig { - netfs_redirect: NetfsRedirect::Always, - ..CacheConfig::default() - }, - ..Config::default() - }; + let config = config_with_cache(CacheConfig { + netfs_redirect: NetfsRedirect::Always, + ..CacheConfig::default() + }); let got = config.cache_dir_for(CacheKind::PypiMapping).unwrap(); assert!(!got.starts_with(node_local_scratch_dir())); @@ -3857,13 +3536,10 @@ UNUSED = "unused" let _disable = ScopedEnv::unset("PIXI_DISABLE_NETFS_REDIRECT"); let _redirect = ScopedEnv::set("PIXI_CACHE_NETFS_REDIRECT", "garbage"); - let config = Config { - cache: CacheConfig { - netfs_redirect: NetfsRedirect::Never, - ..CacheConfig::default() - }, - ..Config::default() - }; + let config = config_with_cache(CacheConfig { + netfs_redirect: NetfsRedirect::Never, + ..CacheConfig::default() + }); // Bad env value → ignored, TOML `never` still applies. let got = config.cache_dir_for(CacheKind::PypiMapping).unwrap(); @@ -3874,14 +3550,91 @@ UNUSED = "unused" fn config_validate_surfaces_cache_errors() { // Config::validate must propagate CacheConfig::validate failures so // bad cache paths are caught at load time, not at first cache use. - let config = Config { - cache: CacheConfig { - conda_packages: Some(PathBuf::from("relative/dir")), - ..CacheConfig::default() - }, - ..Config::default() - }; + let config = config_with_cache(CacheConfig { + conda_packages: Some(PathBuf::from("relative/dir")), + ..CacheConfig::default() + }); let err = config.validate().unwrap_err(); assert!(format!("{err}").contains("cache.conda-packages")); } + + /// Extension keys (pixi-specific keys layered on the shared rattler + /// config) are editable through the upstream *generic* + /// `ConfigBase::set` — no pixi-specific `match` arm involved. + #[test] + fn test_generic_set_handles_extension_keys() { + let mut config = Config::default(); + + // A top-level extension key ... + config + .set("pinning-strategy", Some("semver".to_string())) + .unwrap(); + assert_eq!( + config.extensions.pinning_strategy, + Some(PinningStrategy::Semver) + ); + + // ... a nested extension key ... + config + .set("shell.change-ps1", Some("false".to_string())) + .unwrap(); + assert_eq!(config.extensions.shell.change_ps1, Some(false)); + + // ... and unsetting works too. + config.set("pinning-strategy", None).unwrap(); + assert_eq!(config.extensions.pinning_strategy, None); + + // A typo in an extension key is rejected, and the error lists the + // supported keys — including both shared and extension keys. + let err = config + .set("pinning-strateggy", Some("semver".to_string())) + .unwrap_err(); + let msg = format!("{err}"); + assert!(msg.contains("pinning-strateggy"), "got: {msg}"); + assert!(msg.contains("pinning-strategy"), "got: {msg}"); + assert!(msg.contains("default-channels"), "got: {msg}"); + // ... and the config was not modified. + assert_eq!(config.extensions.pinning_strategy, None); + } + + /// Unknown keys — including typos of extension keys and unknown keys + /// nested inside known extension tables — surface from `from_toml` so + /// the "Ignoring '…' in file" warnings keep working. + #[test] + fn test_from_toml_reports_unknown_extension_keys() { + let toml = r#" + default-channels = ["conda-forge"] + pinning-strategy = "semver" + pinning-strateggy = "semver" + + [shell] + change-ps1 = true + chnge-ps1 = true + + [pypi-config] + index-url = "https://pypi.org/simple" + index-urll = "https://pypi.org/simple" + "#; + let (config, unused) = Config::from_toml(toml, None).unwrap(); + + // Valid keys were consumed by the common config or the extension. + assert_eq!( + config.extensions.pinning_strategy, + Some(PinningStrategy::Semver) + ); + assert_eq!(config.extensions.shell.change_ps1, Some(true)); + assert_eq!( + config.extensions.pypi_config.index_url, + Some(Url::parse("https://pypi.org/simple").unwrap()) + ); + + // The typos are reported, at full depth. + assert!(unused.contains("pinning-strateggy"), "got: {unused:?}"); + assert!(unused.contains("shell.chnge-ps1"), "got: {unused:?}"); + assert!(unused.contains("pypi-config.index-urll"), "got: {unused:?}"); + + // Consumed keys are not reported. + assert!(!unused.contains("pinning-strategy")); + assert!(!unused.iter().any(|k| k == "shell" || k == "pypi-config")); + } } diff --git a/crates/pixi_config/src/snapshots/pixi_config__tests__config_merge_multiple.snap b/crates/pixi_config/src/snapshots/pixi_config__tests__config_merge_multiple.snap index d700319f6b..e1d3d8d455 100644 --- a/crates/pixi_config/src/snapshots/pixi_config__tests__config_merge_multiple.snap +++ b/crates/pixi_config/src/snapshots/pixi_config__tests__config_merge_multiple.snap @@ -1,108 +1,79 @@ --- source: crates/pixi_config/src/lib.rs -assertion_line: 3147 +assertion_line: 2603 expression: debug --- Config { - default_channels: [ - Name( - "conda-forge", - ), - Name( - "bioconda", - ), - Name( - "defaults", - ), - ], - authentication_override_file: None, - tls_no_verify: Some( - false, - ), - tls_root_certs: None, - mirrors: { - Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", - ), + inner: ConfigBase { + common: CommonConfig { + default_channels: Some( + [ + Name( + "conda-forge", + ), + Name( + "bioconda", + ), + Name( + "defaults", + ), + ], ), - port: None, - path: "/conda-forge", - query: None, - fragment: None, - }: [ - Url { - scheme: "whatever", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "config_2", + authentication_override_file: None, + tls_no_verify: Some( + false, + ), + tls_root_certs: None, + mirrors: { + Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "conda.anaconda.org", + ), ), - ), - port: None, - path: "", - query: None, - fragment: None, + port: None, + path: "/conda-forge", + query: None, + fragment: None, + }: [ + Url { + scheme: "whatever", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "config_2", + ), + ), + port: None, + path: "", + query: None, + fragment: None, + }, + ], }, - ], - }, - pinning_strategy: None, - loaded_from: [ - "path/config_2.toml", - "path/config_1.toml", - ], - channel_config: ChannelConfig { - channel_alias: Url { - scheme: "https", - cannot_be_a_base: false, - username: "", - password: None, - host: Some( - Domain( - "conda.anaconda.org", + build: BuildConfig { + package_format: Some( + PackageFormatAndCompression { + archive_type: Conda, + compression_level: Highest, + }, ), - ), - port: None, - path: "/", - query: None, - fragment: None, - }, - root_dir: "/root/dir", - }, - repodata_config: RepodataConfig { - default: RepodataChannelConfig { - disable_bzip2: None, - disable_zstd: Some( - true, - ), - disable_sharded: None, - }, - per_channel: {}, - }, - pypi_config: PyPIConfig { - index_url: None, - extra_index_urls: [], - keyring_provider: None, - allow_insecure_host: [], - }, - s3_options: S3OptionsMap( - { - "bucket1": S3Options { - endpoint_url: Url { + }, + channel_config: ChannelConfig { + channel_alias: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some( Domain( - "my-s3-host", + "conda.anaconda.org", ), ), port: None, @@ -110,59 +81,107 @@ Config { query: None, fragment: None, }, - region: "us-east-1", - force_path_style: false, + root_dir: "/root/dir", + }, + repodata_config: RepodataConfig { + default: RepodataChannelConfig { + disable_bzip2: None, + disable_zstd: Some( + true, + ), + disable_sharded: None, + }, + per_channel: {}, + }, + concurrency: ConcurrencyConfig { + solves: 1, + downloads: 50, + }, + proxy_config: ProxyConfig { + https: None, + http: None, + non_proxy_hosts: [], + }, + s3_options: S3OptionsMap( + { + "bucket1": S3Options { + endpoint_url: Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "my-s3-host", + ), + ), + port: None, + path: "/", + query: None, + fragment: None, + }, + region: "us-east-1", + force_path_style: false, + }, + }, + ), + index_config: IndexConfig { + default: IndexChannelConfig { + write_zst: None, + write_shards: None, + repodata_revisions: None, + package_revision_assignment: None, + base_url: None, + channel_relations: None, + }, + per_channel: {}, }, + run_post_link_scripts: None, + allow_symbolic_links: None, + allow_hard_links: None, + allow_ref_links: None, }, - ), - detached_environments: Some( - Boolean( - true, - ), - ), - shell: ShellConfig { - force_activate: None, - source_completion_scripts: None, - change_ps1: Some( - true, - ), - }, - experimental: ExperimentalConfig { - use_environment_activation_cache: None, - }, - concurrency: ConcurrencyConfig { - solves: 1, - downloads: 50, - }, - run_post_link_scripts: None, - allow_symbolic_links: None, - allow_hard_links: None, - allow_ref_links: None, - proxy_config: ProxyConfig { - https: None, - http: None, - non_proxy_hosts: [], - }, - build: BuildConfig { - package_format: Some( - PackageFormatAndCompression { - archive_type: Conda, - compression_level: Highest, + extensions: PixiConfig { + pinning_strategy: None, + pypi_config: PyPIConfig { + index_url: None, + extra_index_urls: [], + keyring_provider: None, + allow_insecure_host: [], }, - ), - }, - tool_platform: None, - cache: CacheConfig { - root: None, - conda_packages: None, - repodata: None, - pypi_wheels: None, - pypi_mapping: None, - exec_environments: None, - build_tool_environments: None, - detached_environments: None, - netfs_redirect: Auto, + detached_environments: Some( + Boolean( + true, + ), + ), + shell: ShellConfig { + force_activate: None, + source_completion_scripts: None, + change_ps1: Some( + true, + ), + }, + experimental: ExperimentalConfig { + use_environment_activation_cache: None, + }, + tool_platform: None, + cache: CacheConfig { + root: None, + conda_packages: None, + repodata: None, + pypi_wheels: None, + pypi_mapping: None, + exec_environments: None, + build_tool_environments: None, + detached_environments: None, + netfs_redirect: Auto, + }, + change_ps1: None, + force_activate: None, + }, + loaded_from: [ + "path/config_1.toml", + "path/config_2.toml", + ], }, - change_ps1: None, - force_activate: None, } diff --git a/crates/pixi_core/src/workspace/mod.rs b/crates/pixi_core/src/workspace/mod.rs index f472427341..477f88796b 100644 --- a/crates/pixi_core/src/workspace/mod.rs +++ b/crates/pixi_core/src/workspace/mod.rs @@ -1893,11 +1893,12 @@ platforms = [] WORKSPACE_MANIFEST_STR, ) .unwrap() - .with_cli_config(Config { - detached_environments: Some(DetachedEnvironments::Path( + .with_cli_config({ + let mut config = Config::default(); + config.extensions.detached_environments = Some(DetachedEnvironments::Path( detached_dir.path().to_path_buf(), - )), - ..Default::default() + )); + config }); let dot_pixi = dunce::canonicalize(workspace_dir.path()) @@ -1945,9 +1946,11 @@ platforms = [] WORKSPACE_MANIFEST_STR, ) .unwrap() - .with_cli_config(Config { - detached_environments: Some(DetachedEnvironments::Path(detached_dir.to_path_buf())), - ..Default::default() + .with_cli_config({ + let mut config = Config::default(); + config.extensions.detached_environments = + Some(DetachedEnvironments::Path(detached_dir.to_path_buf())); + config }) }; @@ -1979,11 +1982,12 @@ platforms = [] WORKSPACE_MANIFEST_STR, ) .unwrap() - .with_cli_config(Config { - detached_environments: Some(DetachedEnvironments::Path( + .with_cli_config({ + let mut config = Config::default(); + config.extensions.detached_environments = Some(DetachedEnvironments::Path( detached_dir.path().to_path_buf(), - )), - ..Default::default() + )); + config }); let default_envs_dir = workspace.default_environments_dir(); diff --git a/crates/pixi_core/src/workspace/workspace_mut.rs b/crates/pixi_core/src/workspace/workspace_mut.rs index c5b182a8df..ae137b5bba 100644 --- a/crates/pixi_core/src/workspace/workspace_mut.rs +++ b/crates/pixi_core/src/workspace/workspace_mut.rs @@ -604,7 +604,7 @@ impl WorkspaceMut { let channel_config = self.workspace().channel_config(); for (name, (spec_type, spec)) in conda_specs_to_add_constraints_for { - let mut pinning_strategy = self.workspace().config().pinning_strategy; + let mut pinning_strategy = self.workspace().config().pinning_strategy(); // Edge case: some packages are a special case where we want to pin the minor // version by default. This is done to avoid early user confusion @@ -694,7 +694,7 @@ impl WorkspaceMut { let pinning_strategy = self .workspace() .config() - .pinning_strategy + .pinning_strategy() .unwrap_or_default(); // Determine the versions of the packages in the lock file diff --git a/crates/pixi_utils/src/reqwest.rs b/crates/pixi_utils/src/reqwest.rs index 5338735640..e21b7ce8df 100644 --- a/crates/pixi_utils/src/reqwest.rs +++ b/crates/pixi_utils/src/reqwest.rs @@ -102,14 +102,13 @@ fn resolve_tls_root_certs(config: Option<&Config>) -> pixi_config::TlsRootCerts /// `false` -> fall back to the bundled Mozilla webpki roots. /// /// Mirrors pixi's resolved [`pixi_config::TlsRootCerts`]: only `System` -/// (and the deprecated `LegacyNative` alias) maps to `true`. The deprecated -/// `All` mode falls through to `false`; see `load_root_certificates` for the -/// runtime warning. -#[allow(deprecated)] +/// (including the deprecated `native` spelling, which deserializes as +/// `System`) maps to `true`. The deprecated `all` spelling also resolves to +/// `System` — merging both stores is no longer supported. pub fn should_use_system_certs_for_uv(config: &Config) -> bool { matches!( resolve_tls_root_certs(Some(config)), - pixi_config::TlsRootCerts::System | pixi_config::TlsRootCerts::LegacyNative + pixi_config::TlsRootCerts::System ) } @@ -174,7 +173,6 @@ pub fn reqwest_client_builder(config: Option<&Config>) -> miette::Result { + pixi_config::TlsRootCerts::System => { if let Some(env_certs) = Certificates::from_env() { for cert in env_certs.to_reqwest_certs() { builder = builder.add_root_certificate(cert); diff --git a/crates/pixi_utils/src/tls.rs b/crates/pixi_utils/src/tls.rs index 29b05b379f..6eda864154 100644 --- a/crates/pixi_utils/src/tls.rs +++ b/crates/pixi_utils/src/tls.rs @@ -23,20 +23,17 @@ impl Certificates { /// 1. `SSL_CERT_FILE` / `SSL_CERT_DIR` env vars (if set and valid) /// 2. The configured [`TlsRootCerts`] mode /// - /// Deprecation warnings for the legacy [`TlsRootCerts::LegacyNative`] and - /// [`TlsRootCerts::All`] spellings fire once at config-load time - /// (`Config::from_toml`), so this function stays silent. + /// Deprecation warnings for the legacy `"native"` and `"all"` spellings + /// (which deserialize as [`TlsRootCerts::System`]) fire once at + /// config-load time (`Config::from_toml`), so this function stays silent. pub fn for_mode(mode: TlsRootCerts) -> Self { if let Some(env_certs) = Self::from_env() { return env_certs; } - #[allow(deprecated)] match mode { TlsRootCerts::Webpki => Self::webpki_roots(), - TlsRootCerts::System | TlsRootCerts::LegacyNative | TlsRootCerts::All => { - Self::from_native_store() - } + TlsRootCerts::System => Self::from_native_store(), } } diff --git a/crates/pixi_uv_context/src/lib.rs b/crates/pixi_uv_context/src/lib.rs index 8e6965f74b..ed8d41cf42 100644 --- a/crates/pixi_uv_context/src/lib.rs +++ b/crates/pixi_uv_context/src/lib.rs @@ -161,7 +161,7 @@ impl UvResolutionContext { let cache = Cache::from_path(uv_cache); - let keyring_provider = match config.pypi_config.use_keyring() { + let keyring_provider = match config.pypi_config().use_keyring() { pixi_config::KeyringProvider::Subprocess => { tracing::debug!("using uv keyring (subprocess) provider"); uv_configuration::KeyringProviderType::Subprocess @@ -173,7 +173,7 @@ impl UvResolutionContext { }; let allow_insecure_host = config - .pypi_config + .pypi_config() .allow_insecure_host .iter() .try_fold( From 047116ce471bb07f89369206dfc69c7d5376635b Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 6 Jul 2026 08:33:35 +0000 Subject: [PATCH 2/5] test(pixi_config): add compatibility test catalog for the full config schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pixi-side mirror of rattler_config's tests/compat.rs: that catalog pins the contract of the shared keys; this one pins the whole pixi schema (shared CommonConfig keys plus the PixiConfig extension) so upgrading the shared config crate can never silently break a user's existing config.toml. New: crates/pixi_config/tests/compat.rs + test-data/compat/ fixtures (kitchen-sink, snake-case-aliases, legacy-config, typos, override-layer) + insta snapshots. Coverage: 1. Parsing permutations — every fixture parses; (unused keys, parsed Config) snapshotted per fixture (channel_config.root_dir normalized so snapshots are machine-independent). snake_case aliases parse equal to canonical with zero warnings; a realistic old pixi config (change-ps1, force-activate, tls-root-certs = "native", detached-environments = true, repodata-config.disable-jlap) loads with warnings only, and the deprecated values still take effect through the modern accessors (change_ps1()/force_activate() see the folded shell.* values, "native" resolves to the system store); typos of shared AND extension keys, top-level and nested, are all reported as unused while valid neighbors survive. 2. Round-trip stability — load -> to_toml -> load is lossless and idempotent for all five fixtures (including the legacy one: the deprecated keys re-serialize and re-fold identically), and serialization never invents unknown keys. 3. Editing matrix — 42 entries through the public Config::set (the `pixi config set` code path): every shared key family plus pinning-strategy, detached-environments (true/false/path), tool-platform, pypi-config.*, shell.*, experimental.use-environment-activation-cache and all cache.* keys (absolute paths, since set re-validates). Each entry: set succeeds on a fully populated config, the result round-trips, and set+unset on a pristine config restores the default. Deprecated change-ps1/force-activate stay hard errors pointing at shell.*, and unknown keys (shared and extension typos) are rejected in both set and unset direction. 4. Merge semantics — kitchen-sink + override layer through Config::merge_config: scalars replace, mirrors/s3-options extend, repodata merges field-wise (default and per-channel), pypi index-url replaces while extra-index-urls/allow-insecure-host extend, shell/experimental/cache merge field-wise, and the long-standing tool-platform LOWER-layer-wins quirk is pinned with a comment so changing it becomes a conscious decision. Merged output snapshotted. The catalog immediately caught a real bug: the pinned rattler commit (33a4909) still had the repodata merge direction inverted (the lower layer's disable-bzip2 survived an override). conda/rattler already fixed this on the same branch in 5ded1a9 ("fix repodata merge direction") — this commit bumps Cargo.lock to that rev, which makes the merge test pass. None of the pre-existing pixi tests noticed the inverted direction, which is exactly the gap this catalog closes. Tests: cargo test -p pixi_config (55 unit + 9 compat) passes both with proxy env scrubbed and with HTTPS_PROXY/HTTP_PROXY set; cargo check --workspace --all-targets; clippy clean on pixi_config; cargo fmt. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01EzYs4p6XJDj9QBcNB4ipR7 --- Cargo.lock | 54 +-- .../test-data/compat/kitchen-sink.toml | 79 ++++ .../test-data/compat/legacy-config.toml | 20 + .../test-data/compat/override-layer.toml | 40 ++ .../test-data/compat/snake-case-aliases.toml | 17 + .../pixi_config/test-data/compat/typos.toml | 17 + crates/pixi_config/tests/compat.rs | 412 ++++++++++++++++++ ...at__merge__kitchen_sink_plus_override.snap | 88 ++++ .../compat__parse__kitchen-sink.toml.snap | 341 +++++++++++++++ .../compat__parse__legacy-config.toml.snap | 149 +++++++ .../compat__parse__override-layer.toml.snap | 237 ++++++++++ ...ompat__parse__snake-case-aliases.toml.snap | 133 ++++++ .../snapshots/compat__parse__typos.toml.snap | 121 +++++ 13 files changed, 1681 insertions(+), 27 deletions(-) create mode 100644 crates/pixi_config/test-data/compat/kitchen-sink.toml create mode 100644 crates/pixi_config/test-data/compat/legacy-config.toml create mode 100644 crates/pixi_config/test-data/compat/override-layer.toml create mode 100644 crates/pixi_config/test-data/compat/snake-case-aliases.toml create mode 100644 crates/pixi_config/test-data/compat/typos.toml create mode 100644 crates/pixi_config/tests/compat.rs create mode 100644 crates/pixi_config/tests/snapshots/compat__merge__kitchen_sink_plus_override.snap create mode 100644 crates/pixi_config/tests/snapshots/compat__parse__kitchen-sink.toml.snap create mode 100644 crates/pixi_config/tests/snapshots/compat__parse__legacy-config.toml.snap create mode 100644 crates/pixi_config/tests/snapshots/compat__parse__override-layer.toml.snap create mode 100644 crates/pixi_config/tests/snapshots/compat__parse__snake-case-aliases.toml.snap create mode 100644 crates/pixi_config/tests/snapshots/compat__parse__typos.toml.snap diff --git a/Cargo.lock b/Cargo.lock index 3b2d57d82b..bd6ca3aa1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1680,7 +1680,7 @@ dependencies = [ [[package]] name = "coalesced_map" version = "0.1.3" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "dashmap", "tokio", @@ -2860,7 +2860,7 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "file_url" version = "0.3.1" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "itertools 0.14.0", "percent-encoding", @@ -3829,7 +3829,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.3", + "socket2 0.5.10", "system-configuration", "tokio", "tower-service", @@ -5758,7 +5758,7 @@ checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" [[package]] name = "path_resolver" version = "0.2.11" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "ahash", "fs-err", @@ -7807,7 +7807,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.3", + "socket2 0.5.10", "thiserror 2.0.18", "tokio", "tracing", @@ -7845,7 +7845,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.3", + "socket2 0.5.10", "tracing", "windows-sys 0.59.0", ] @@ -7980,7 +7980,7 @@ dependencies = [ [[package]] name = "rattler" version = "0.46.0" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "anyhow", "astral-reqwest-middleware", @@ -8300,7 +8300,7 @@ dependencies = [ [[package]] name = "rattler_cache" version = "0.10.1" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "ahash", "anyhow", @@ -8333,7 +8333,7 @@ dependencies = [ [[package]] name = "rattler_conda_types" version = "0.47.2" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "ahash", "core-foundation 0.10.1", @@ -8375,7 +8375,7 @@ dependencies = [ [[package]] name = "rattler_config" version = "0.5.2" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "dirs", "fs-err", @@ -8393,7 +8393,7 @@ dependencies = [ [[package]] name = "rattler_digest" version = "1.3.1" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "blake2 0.11.0-rc.6", "digest 0.11.3", @@ -8433,7 +8433,7 @@ dependencies = [ [[package]] name = "rattler_index" version = "0.30.7" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "ahash", "anyhow", @@ -8472,7 +8472,7 @@ dependencies = [ [[package]] name = "rattler_lock" version = "0.31.3" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "ahash", "file_url", @@ -8500,7 +8500,7 @@ dependencies = [ [[package]] name = "rattler_macros" version = "1.1.1" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "quote", "syn", @@ -8509,7 +8509,7 @@ dependencies = [ [[package]] name = "rattler_menuinst" version = "0.2.68" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "configparser", "dirs", @@ -8539,7 +8539,7 @@ dependencies = [ [[package]] name = "rattler_networking" version = "0.30.0" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "ambient-id", "anyhow", @@ -8578,7 +8578,7 @@ dependencies = [ [[package]] name = "rattler_package_streaming" version = "0.26.6" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "astral-reqwest-middleware", "astral-tokio-tar", @@ -8632,7 +8632,7 @@ dependencies = [ [[package]] name = "rattler_pty" version = "0.2.14" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "libc", "nix 0.30.1", @@ -8643,7 +8643,7 @@ dependencies = [ [[package]] name = "rattler_redaction" version = "0.2.1" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "astral-reqwest-middleware", "reqwest", @@ -8653,7 +8653,7 @@ dependencies = [ [[package]] name = "rattler_repodata_gateway" version = "0.29.7" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "ahash", "anyhow", @@ -8715,7 +8715,7 @@ dependencies = [ [[package]] name = "rattler_s3" version = "0.2.6" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "aws-config", "aws-credential-types", @@ -8731,7 +8731,7 @@ dependencies = [ [[package]] name = "rattler_shell" version = "0.27.8" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "anyhow", "enum_dispatch", @@ -8752,7 +8752,7 @@ dependencies = [ [[package]] name = "rattler_solve" version = "7.2.0" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "futures", "hex", @@ -8770,7 +8770,7 @@ dependencies = [ [[package]] name = "rattler_upload" version = "0.8.2" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "astral-reqwest-middleware", "astral-reqwest-retry", @@ -8808,7 +8808,7 @@ dependencies = [ [[package]] name = "rattler_virtual_packages" version = "3.0.2" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "archspec", "libloading", @@ -10448,7 +10448,7 @@ dependencies = [ [[package]] name = "simple_spawn_blocking" version = "1.1.0" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#33a490915be0ad2f706697a84f47567d1e306b6e" +source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" dependencies = [ "tokio", ] @@ -10819,7 +10819,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.2", "once_cell", "rustix 1.1.4", "windows-sys 0.61.2", diff --git a/crates/pixi_config/test-data/compat/kitchen-sink.toml b/crates/pixi_config/test-data/compat/kitchen-sink.toml new file mode 100644 index 0000000000..561209cc2a --- /dev/null +++ b/crates/pixi_config/test-data/compat/kitchen-sink.toml @@ -0,0 +1,79 @@ +# Every pixi configuration key, canonical (kebab-case) spelling: the shared +# rattler keys plus pixi's extension keys. Values are realistic (taken from +# the pixi documentation where possible). + +# ---- shared keys (rattler_config::CommonConfig) ---- +default-channels = ["conda-forge", "bioconda"] +authentication-override-file = "/path/to/auth.json" +tls-no-verify = false +tls-root-certs = "webpki" +run-post-link-scripts = "insecure" +allow-symbolic-links = true +allow-hard-links = false +allow-ref-links = true + +# ---- pixi extension keys (PixiConfig), scalar part ---- +pinning-strategy = "no-pin" +detached-environments = "/opt/pixi/envs" +tool-platform = "linux-64" + +[mirrors] +"https://conda.anaconda.org/conda-forge" = [ + "https://prefix.dev/conda-forge", + "https://repo.prefix.dev/conda-forge", +] + +[build] +package-format = "conda:max" + +[repodata-config] +disable-bzip2 = true +disable-zstd = false +disable-sharded = false + +[repodata-config."https://prefix.dev"] +disable-sharded = true + +[concurrency] +solves = 4 +downloads = 12 + +[proxy-config] +https = "https://proxy.example.com:8080" +http = "http://proxy.example.com:8080" +non-proxy-hosts = ["localhost", "127.0.0.1"] + +[s3-options.my-bucket] +endpoint-url = "https://my-s3-host" +region = "us-east-1" +force-path-style = true + +[index-config] +write-zst = true +write-shards = false + +# ---- pixi extension keys (PixiConfig), table part ---- +[pypi-config] +index-url = "https://pypi.org/simple" +extra-index-urls = ["https://example.com/simple"] +keyring-provider = "subprocess" +allow-insecure-host = ["localhost:8080"] + +[shell] +change-ps1 = false +force-activate = true +source-completion-scripts = false + +[experimental] +use-environment-activation-cache = true + +[cache] +root = "/shared/pixi/cache" +conda-packages = "/shared/pixi/cache/pkgs" +repodata = "/scratch/pixi/repodata" +pypi-wheels = "/scratch/pixi/wheels" +pypi-mapping = "/scratch/pixi/mapping" +exec-environments = "/scratch/pixi/exec" +build-tool-environments = "/scratch/pixi/build-tools" +detached-environments = "/shared/pixi/envs" +netfs-redirect = "never" diff --git a/crates/pixi_config/test-data/compat/legacy-config.toml b/crates/pixi_config/test-data/compat/legacy-config.toml new file mode 100644 index 0000000000..1ec0e3bcab --- /dev/null +++ b/crates/pixi_config/test-data/compat/legacy-config.toml @@ -0,0 +1,20 @@ +# A realistic OLD pixi config (pre ~0.40): deprecated top-level keys, the +# legacy `"native"` TLS spelling and a long-removed repodata key next to +# perfectly normal settings. This must PARSE — deprecated values still take +# effect, removed keys only warn, and nothing hard-errors. +default-channels = ["conda-forge"] +change-ps1 = false +force-activate = true +tls-root-certs = "native" # legacy spelling, alias for "system" +detached-environments = true # boolean variant of the bool-or-path key +pinning-strategy = "minor" + +[repodata-config] +disable-bzip2 = true +disable-jlap = true # removed long ago, must only warn + +[pypi-config] +index-url = "https://pypi.org/simple" + +[concurrency] +solves = 2 diff --git a/crates/pixi_config/test-data/compat/override-layer.toml b/crates/pixi_config/test-data/compat/override-layer.toml new file mode 100644 index 0000000000..a79ce11028 --- /dev/null +++ b/crates/pixi_config/test-data/compat/override-layer.toml @@ -0,0 +1,40 @@ +# A second layer merged ON TOP of kitchen-sink.toml in the merge tests +# (i.e. this file has the higher priority). +default-channels = ["robostack"] +tls-no-verify = true +pinning-strategy = "semver" +detached-environments = false +# Deliberately different from kitchen-sink: pins the (long-standing) quirk +# that for tool-platform the LOWER layer wins on merge. +tool-platform = "osx-arm64" + +[mirrors] +"https://conda.anaconda.org/bioconda" = ["https://prefix.dev/bioconda"] + +[repodata-config] +disable-bzip2 = false + +[repodata-config."https://prefix.dev"] +disable-zstd = true + +[concurrency] +solves = 9 + +[s3-options.other-bucket] +endpoint-url = "https://minio.example.com" +region = "auto" +force-path-style = false + +[pypi-config] +index-url = "https://test.pypi.org/simple" +extra-index-urls = ["https://extra.example.com/simple"] + +[shell] +change-ps1 = true + +[experimental] +use-environment-activation-cache = false + +[cache] +root = "/other/pixi/cache" +netfs-redirect = "always" diff --git a/crates/pixi_config/test-data/compat/snake-case-aliases.toml b/crates/pixi_config/test-data/compat/snake-case-aliases.toml new file mode 100644 index 0000000000..60434e5026 --- /dev/null +++ b/crates/pixi_config/test-data/compat/snake-case-aliases.toml @@ -0,0 +1,17 @@ +# Legacy snake_case spellings must keep parsing (serde aliases). This file +# only uses keys that actually carry an alias: +# - the shared keys aliased upstream in rattler_config, and +# - `change_ps1`, the only aliased key in pixi's extension (deprecated, +# folded into `shell.change-ps1` at load time). +default_channels = ["conda-forge"] +authentication_override_file = "/path/to/auth.json" +tls_no_verify = true +tls_root_certs = "system" +allow_symbolic_links = false +allow_hard_links = true +allow_ref_links = false +change_ps1 = false + +[repodata_config] +disable_bzip2 = true +disable_zstd = true diff --git a/crates/pixi_config/test-data/compat/typos.toml b/crates/pixi_config/test-data/compat/typos.toml new file mode 100644 index 0000000000..c9249472d1 --- /dev/null +++ b/crates/pixi_config/test-data/compat/typos.toml @@ -0,0 +1,17 @@ +# Misspelled keys — shared and extension, top-level and nested — must never +# fail the load. Each typo surfaces in the unused-keys set (pixi turns those +# into the "Ignoring '…'" warning); the valid keys around them still load. +default-channels = ["conda-forge"] +pinning-strateggy = "semver" # extension key typo, top level +authentification-override-file = "/path/to/auth.json" # shared key typo, top level + +[shell] +chnge-ps1 = true # extension key typo, nested +force-activate = true # valid neighbor, must survive + +[concurrency] +solvs = 4 # shared key typo, nested +downloads = 8 # valid neighbor, must survive + +[pypi-config] +index-urll = "https://pypi.org/simple" # extension key typo, nested diff --git a/crates/pixi_config/tests/compat.rs b/crates/pixi_config/tests/compat.rs new file mode 100644 index 0000000000..afa3cc3a9d --- /dev/null +++ b/crates/pixi_config/tests/compat.rs @@ -0,0 +1,412 @@ +//! Compatibility test catalog for the full pixi configuration schema. +//! +//! The pixi-side mirror of `rattler_config`'s `tests/compat.rs`: where that +//! catalog pins the contract of the *shared* keys, this one pins the whole +//! pixi schema — the shared keys (through `ConfigBase`/`CommonConfig`) plus +//! pixi's `PixiConfig` extension keys — so upgrading the shared config crate +//! can never silently break a user's existing `config.toml`: +//! +//! 1. **Parsing permutations** — canonical kebab-case, legacy `snake_case` +//! aliases, a realistic old pixi config with deprecated keys, and typos +//! (fixtures in `test-data/compat/`). Deprecated/unknown keys must parse +//! with warnings, never hard errors. +//! 2. **Round-trip stability** — load → serialize → load is lossless and +//! serialization is idempotent, so `pixi config set` + save never +//! corrupts the rest of a user's configuration. +//! 3. **Editing matrix** — every settable key family goes through the public +//! `Config::set`; set+unset on a pristine config restores the default, +//! proving edits have no collateral effect on unrelated keys. +//! 4. **Merge semantics** — how two layered files combine (replace vs extend +//! vs field-wise merge), including the extension fields' legacy quirks. + +use std::{ + collections::BTreeSet, + path::{Path, PathBuf}, +}; + +use pixi_config::{Config, DetachedEnvironments, PinningStrategy, TlsRootCerts}; +use rattler_conda_types::{ChannelConfig, Platform}; + +fn fixture_path(name: &str) -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("test-data/compat") + .join(name) +} + +fn parse(name: &str) -> (Config, BTreeSet) { + let toml = fs_err::read_to_string(fixture_path(name)).unwrap(); + Config::from_toml(&toml, Some(Path::new(name))) + .unwrap_or_else(|e| panic!("{name} must parse: {e}")) +} + +/// `channel_config` is not part of the TOML schema (serde-skipped) and its +/// default embeds the current working directory; pin it to a fixed path so +/// snapshots are machine-independent. +fn normalized(mut config: Config) -> Config { + config.channel_config = ChannelConfig::default_with_root_dir(PathBuf::from("/root/dir")); + config +} + +const FIXTURES: &[&str] = &[ + "kitchen-sink.toml", + "snake-case-aliases.toml", + "legacy-config.toml", + "typos.toml", + "override-layer.toml", +]; + +/// Every fixture must parse; snapshot the parsed result and the reported +/// unused keys so schema changes are reviewed consciously. +#[test] +fn parsing_permutations() { + for name in FIXTURES { + let (config, unused) = parse(name); + insta::assert_debug_snapshot!(format!("parse__{name}"), (unused, normalized(config))); + } +} + +/// Snake-case spellings must parse to the same configuration as their +/// kebab-case equivalents, without any unused-key warnings. +#[test] +fn snake_case_aliases_are_equivalent() { + let (config, unused) = parse("snake-case-aliases.toml"); + assert!(unused.is_empty(), "aliases must not warn: {unused:?}"); + + let canonical = r#" + default-channels = ["conda-forge"] + authentication-override-file = "/path/to/auth.json" + tls-no-verify = true + tls-root-certs = "system" + allow-symbolic-links = false + allow-hard-links = true + allow-ref-links = false + change-ps1 = false + + [repodata-config] + disable-bzip2 = true + disable-zstd = true + "#; + let (canonical, _) = Config::from_toml(canonical, None).unwrap(); + assert_eq!(config, canonical); +} + +/// A realistic old pixi config: deprecated keys and legacy value spellings +/// must keep parsing, and the deprecated values must still take effect +/// through the modern accessors. +#[test] +fn legacy_config_still_takes_effect() { + let (config, unused) = parse("legacy-config.toml"); + + // The only unknown key is the long-removed repodata-config.disable-jlap; + // the deprecated pixi keys are still consumed by the schema itself. + assert_eq!( + unused.into_iter().collect::>(), + ["repodata-config.disable-jlap"] + ); + + // Deprecated top-level keys are folded into their `shell.*` replacements + // at load time, so the modern accessors see them. + assert!(!config.change_ps1(), "change-ps1 = false must take effect"); + assert!( + config.force_activate(), + "force-activate = true must take effect" + ); + assert_eq!(config.shell().change_ps1, Some(false)); + assert_eq!(config.shell().force_activate, Some(true)); + + // The legacy `"native"` spelling resolves to the system trust store. + assert_eq!(config.tls_root_certs(), Some(TlsRootCerts::System)); + + // The boolean variant of the bool-or-path key. + assert_eq!( + config.detached_environments(), + DetachedEnvironments::Boolean(true) + ); + + // Ordinary keys next to the deprecated ones survive. + assert_eq!(config.pinning_strategy(), Some(PinningStrategy::Minor)); + assert_eq!(config.max_concurrent_solves(), 2); + assert_eq!(config.repodata_config.default.disable_bzip2, Some(true)); + assert_eq!( + config + .pypi_config() + .index_url + .as_ref() + .map(url::Url::as_str), + Some("https://pypi.org/simple") + ); +} + +/// Misspelled keys — shared and extension, top level and nested — are all +/// reported as unused (pixi warns), while their valid neighbors still load. +#[test] +fn typos_warn_but_neighbors_survive() { + let (config, unused) = parse("typos.toml"); + + for key in [ + "pinning-strateggy", // extension, top level + "authentification-override-file", // shared, top level + "shell.chnge-ps1", // extension, nested + "concurrency.solvs", // shared, nested + "pypi-config.index-urll", // extension, nested + ] { + assert!( + unused.contains(key), + "{key} must be reported, got {unused:?}" + ); + } + + assert_eq!(config.default_channels.as_ref().map(Vec::len), Some(1)); + assert!(config.force_activate()); + assert_eq!(config.max_concurrent_downloads(), 8); +} + +/// load → serialize → load must be lossless, and serialization idempotent. +/// This is what guarantees that `pixi config set` + `save` never corrupts +/// the rest of a user's configuration. Note this holds even for the legacy +/// fixture: the deprecated keys re-serialize and re-fold identically. +#[test] +fn round_trip_is_lossless_and_idempotent() { + for name in FIXTURES { + let (config, _) = parse(name); + let first = config.to_toml().unwrap(); + let (reloaded, unused) = Config::from_toml(&first, None).unwrap(); + assert!( + unused.is_empty(), + "{name}: serialization must not invent unknown keys: {unused:?}" + ); + assert_eq!(config, reloaded, "{name}: round trip must be lossless"); + let second = reloaded.to_toml().unwrap(); + assert_eq!(first, second, "{name}: serialization must be idempotent"); + } +} + +/// The editing matrix: one entry per settable key family with a +/// representative value, all driven through the public `Config::set` (the +/// same code path as `pixi config set`). Extend this list whenever a key is +/// added to `CommonConfig` or `PixiConfig`. +const EDIT_MATRIX: &[(&str, &str)] = &[ + // ---- shared keys ---- + ("default-channels", r#"["conda-forge"]"#), + ("authentication-override-file", "/tmp/auth.json"), + ("tls-no-verify", "true"), + ("tls-root-certs", "webpki"), + ( + "mirrors", + r#"{"https://conda.anaconda.org/conda-forge": ["https://prefix.dev/conda-forge"]}"#, + ), + ("run-post-link-scripts", "insecure"), + ("allow-symbolic-links", "false"), + ("allow-hard-links", "true"), + ("allow-ref-links", "false"), + ("build.package-format", "conda:max"), + ("repodata-config.disable-bzip2", "true"), + ("repodata-config.disable-zstd", "false"), + ("repodata-config.disable-sharded", "true"), + ("concurrency.solves", "3"), + ("concurrency.downloads", "21"), + ("proxy-config.https", "https://proxy.example.com:8080"), + ("proxy-config.http", "http://proxy.example.com:8080"), + ("proxy-config.non-proxy-hosts", r#"["localhost"]"#), + ( + "s3-options.some-bucket", + r#"{"endpoint-url": "https://s3.example.com", "region": "auto", "force-path-style": true}"#, + ), + // ---- pixi extension keys ---- + ("pinning-strategy", "no-pin"), + ("detached-environments", "true"), + ("detached-environments", "false"), + ("detached-environments", "/opt/pixi/envs"), + ("tool-platform", "linux-64"), + ("pypi-config.index-url", "https://pypi.org/simple"), + ( + "pypi-config.extra-index-urls", + r#"["https://example.com/simple"]"#, + ), + ("pypi-config.keyring-provider", "subprocess"), + ("pypi-config.allow-insecure-host", r#"["localhost:8080"]"#), + ("shell.change-ps1", "false"), + ("shell.force-activate", "true"), + ("shell.source-completion-scripts", "false"), + ("experimental.use-environment-activation-cache", "true"), + // `[cache]` paths must be absolute (Config::set re-validates), so the + // matrix uses absolute values. + ("cache.root", "/shared/pixi/cache"), + ("cache.conda-packages", "/shared/pixi/cache/pkgs"), + ("cache.repodata", "/scratch/pixi/repodata"), + ("cache.pypi-wheels", "/scratch/pixi/wheels"), + ("cache.pypi-mapping", "/scratch/pixi/mapping"), + ("cache.exec-environments", "/scratch/pixi/exec"), + ("cache.build-tool-environments", "/scratch/pixi/build-tools"), + ("cache.detached-environments", "/shared/pixi/envs"), + ("cache.netfs-redirect", "never"), +]; + +/// Every key in the matrix can be set on a fully populated config, the +/// result still round-trips, and set+unset on a pristine config restores +/// the default (proving no collateral damage to unrelated keys). +#[test] +fn edit_matrix_set_roundtrip_unset() { + let (kitchen_sink, _) = parse("kitchen-sink.toml"); + + for (key, value) in EDIT_MATRIX { + // set on a fully populated config … + let mut edited = kitchen_sink.clone(); + edited + .set(key, Some((*value).to_string())) + .unwrap_or_else(|e| panic!("set {key}={value} must succeed: {e}")); + + // … and the result still round-trips losslessly. + let toml = edited.to_toml().unwrap(); + let (reloaded, unused) = Config::from_toml(&toml, None).unwrap(); + assert!(unused.is_empty(), "{key}: no unknown keys after edit"); + assert_eq!(edited, reloaded, "{key}: round trip after edit"); + + // set + unset on a pristine config restores the default state, + // proving the edit touched nothing else. + let mut pristine = Config::default(); + pristine.set(key, Some((*value).to_string())).unwrap(); + assert_ne!(pristine, Config::default(), "{key}: set must change state"); + pristine.set(key, None).unwrap(); + assert_eq!( + pristine, + Config::default(), + "{key}: unset must restore the default without collateral changes" + ); + } +} + +/// The deprecated top-level keys are a hard error in `set` (unlike file +/// loading, where they are tolerated and folded): interactive edits must +/// steer users to the `shell.*` replacements. +#[test] +fn edit_rejects_deprecated_keys_with_pointer() { + let mut config = Config::default(); + for (old, new) in [ + ("change-ps1", "shell.change-ps1"), + ("force-activate", "shell.force-activate"), + ] { + let err = config + .set(old, Some("true".to_string())) + .expect_err("deprecated keys must hard-error in set"); + assert!( + err.to_string().contains(new), + "error for {old} must point at {new}: {err}" + ); + } +} + +/// Unknown keys must be rejected by `set` (both set and unset direction), +/// for shared and extension key typos alike. +#[test] +fn edit_rejects_unknown_keys() { + let mut config = Config::default(); + for key in [ + "definitely-a-typo", + "pinning-strateggy", + "shell.chnge-ps1", + "concurrency.bogus", + ] { + assert!( + config.set(key, Some("1".to_string())).is_err(), + "set {key} must be rejected" + ); + assert!( + config.set(key, None).is_err(), + "unset {key} must be rejected" + ); + } +} + +/// Merge semantics per key family: scalars are replaced, mirrors/s3 extend, +/// nested tables merge field-wise, and the pixi extension fields keep their +/// legacy semantics. Snapshot the merged result so semantic changes are +/// reviewed consciously. +#[test] +fn merge_semantics() { + let (base, _) = parse("kitchen-sink.toml"); + let (layer, _) = parse("override-layer.toml"); + // `other` (the layer) has the higher priority. + let merged = base.merge_config(layer); + + // ---- shared keys ---- + // scalars/lists: later layer replaces. + assert_eq!( + merged.default_channels.as_ref().map(|c| c[0].to_string()), + Some("robostack".to_string()) + ); + assert_eq!(merged.tls_no_verify, Some(true)); + // maps: later layer extends. + assert_eq!(merged.mirrors.len(), 2); + assert_eq!(merged.s3_options.0.len(), 2); + // nested tables merge field-wise; unset fields keep the lower layer. + assert_eq!(merged.repodata_config.default.disable_bzip2, Some(false)); + assert_eq!(merged.repodata_config.default.disable_zstd, Some(false)); + let prefix_dev = url::Url::parse("https://prefix.dev").unwrap(); + let per_channel = &merged.repodata_config.per_channel[&prefix_dev]; + assert_eq!(per_channel.disable_sharded, Some(true)); // from the base layer + assert_eq!(per_channel.disable_zstd, Some(true)); // from the override layer + // concurrency: explicitly set values win over the lower layer. + assert_eq!(merged.max_concurrent_solves(), 9); + assert_eq!(merged.max_concurrent_downloads(), 12); + + // ---- pixi extension keys ---- + // scalars: later layer replaces. + assert_eq!(merged.pinning_strategy(), Some(PinningStrategy::Semver)); + assert_eq!( + merged.detached_environments(), + DetachedEnvironments::Boolean(false) + ); + // QUIRK (pinned on purpose): for `tool-platform` the LOWER layer wins. + // This is the long-standing behavior of the former `Config::merge_config` + // (`self.tool_platform.or(other.tool_platform)`), preserved verbatim in + // `PixiConfig::merge_config`. If this assertion ever fails, the merge + // direction was changed — make that a conscious, documented decision. + assert_eq!(merged.tool_platform(), Platform::Linux64); + // pypi-config: index-url replaces, the url/host lists EXTEND (base + // first), keyring-provider keeps the base when the layer is silent. + let pypi = merged.pypi_config(); + assert_eq!( + pypi.index_url.as_ref().map(url::Url::as_str), + Some("https://test.pypi.org/simple") + ); + assert_eq!( + pypi.extra_index_urls + .iter() + .map(url::Url::as_str) + .collect::>(), + [ + "https://example.com/simple", + "https://extra.example.com/simple" + ] + ); + assert_eq!(pypi.allow_insecure_host, vec!["localhost:8080".to_string()]); + assert!(matches!( + pypi.keyring_provider, + Some(pixi_config::KeyringProvider::Subprocess) + )); + // shell: field-wise merge. + assert_eq!(merged.shell().change_ps1, Some(true)); // overridden + assert_eq!(merged.shell().force_activate, Some(true)); // from the base + assert!(!merged.shell().source_completion_scripts()); // from the base + // experimental: later layer replaces when set. + assert!(!merged.experimental_activation_cache_usage()); + // cache: field-wise merge; non-default netfs-redirect wins. + assert_eq!( + merged.cache().root.as_deref(), + Some(Path::new("/other/pixi/cache")) + ); + assert_eq!( + merged.cache().conda_packages.as_deref(), + Some(Path::new("/shared/pixi/cache/pkgs")) + ); + assert_eq!( + merged.cache().netfs_redirect, + pixi_config::NetfsRedirect::Always + ); + + insta::assert_snapshot!( + "merge__kitchen_sink_plus_override", + merged.to_toml().unwrap() + ); +} diff --git a/crates/pixi_config/tests/snapshots/compat__merge__kitchen_sink_plus_override.snap b/crates/pixi_config/tests/snapshots/compat__merge__kitchen_sink_plus_override.snap new file mode 100644 index 0000000000..0e8119ebb5 --- /dev/null +++ b/crates/pixi_config/tests/snapshots/compat__merge__kitchen_sink_plus_override.snap @@ -0,0 +1,88 @@ +--- +source: crates/pixi_config/tests/compat.rs +expression: merged.to_toml().unwrap() +--- +default-channels = ["robostack"] +authentication-override-file = "/path/to/auth.json" +tls-no-verify = true +tls-root-certs = "webpki" +run-post-link-scripts = "insecure" +allow-symbolic-links = true +allow-hard-links = false +allow-ref-links = true +pinning-strategy = "semver" +detached-environments = false +tool-platform = "linux-64" + +[mirrors] +"https://conda.anaconda.org/conda-forge" = [ + "https://prefix.dev/conda-forge", + "https://repo.prefix.dev/conda-forge", +] +"https://conda.anaconda.org/bioconda" = ["https://prefix.dev/bioconda"] + +[build] +package-format = "conda:max" + +[repodata-config] +disable-bzip2 = false +disable-zstd = false +disable-sharded = false + +[repodata-config."https://prefix.dev/"] +disable-zstd = true +disable-sharded = true + +[concurrency] +solves = 9 +downloads = 12 + +[proxy-config] +https = "https://proxy.example.com:8080/" +http = "http://proxy.example.com:8080/" +non-proxy-hosts = [ + "localhost", + "127.0.0.1", +] + +[s3-options.my-bucket] +endpoint-url = "https://my-s3-host/" +region = "us-east-1" +force-path-style = true + +[s3-options.other-bucket] +endpoint-url = "https://minio.example.com/" +region = "auto" +force-path-style = false + +[index-config] +write-zst = true +write-shards = false + +[pypi-config] +index-url = "https://test.pypi.org/simple" +extra-index-urls = [ + "https://example.com/simple", + "https://extra.example.com/simple", +] +keyring-provider = "subprocess" +allow-insecure-host = ["localhost:8080"] + +[shell] +force-activate = true +source-completion-scripts = false +change-ps1 = true + +[experimental] +use-environment-activation-cache = false + +[cache] +root = "/other/pixi/cache" +conda-packages = "/shared/pixi/cache/pkgs" +repodata = "/scratch/pixi/repodata" +pypi-wheels = "/scratch/pixi/wheels" +pypi-mapping = "/scratch/pixi/mapping" +exec-environments = "/scratch/pixi/exec" +build-tool-environments = "/scratch/pixi/build-tools" +detached-environments = "/shared/pixi/envs" +netfs-redirect = "always" diff --git a/crates/pixi_config/tests/snapshots/compat__parse__kitchen-sink.toml.snap b/crates/pixi_config/tests/snapshots/compat__parse__kitchen-sink.toml.snap new file mode 100644 index 0000000000..0da6131aef --- /dev/null +++ b/crates/pixi_config/tests/snapshots/compat__parse__kitchen-sink.toml.snap @@ -0,0 +1,341 @@ +--- +source: crates/pixi_config/tests/compat.rs +expression: "(unused, normalized(config))" +--- +( + {}, + Config { + inner: ConfigBase { + common: CommonConfig { + default_channels: Some( + [ + Name( + "conda-forge", + ), + Name( + "bioconda", + ), + ], + ), + authentication_override_file: Some( + "/path/to/auth.json", + ), + tls_no_verify: Some( + false, + ), + tls_root_certs: Some( + Webpki, + ), + mirrors: { + 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, + }: [ + Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "prefix.dev", + ), + ), + port: None, + path: "/conda-forge", + query: None, + fragment: None, + }, + Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "repo.prefix.dev", + ), + ), + port: None, + path: "/conda-forge", + query: None, + fragment: None, + }, + ], + }, + build: BuildConfig { + package_format: Some( + PackageFormatAndCompression { + archive_type: Conda, + compression_level: Highest, + }, + ), + }, + channel_config: ChannelConfig { + channel_alias: Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "conda.anaconda.org", + ), + ), + port: None, + path: "/", + query: None, + fragment: None, + }, + root_dir: "/root/dir", + }, + repodata_config: RepodataConfig { + default: RepodataChannelConfig { + disable_bzip2: Some( + true, + ), + disable_zstd: Some( + false, + ), + disable_sharded: Some( + false, + ), + }, + per_channel: { + Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "prefix.dev", + ), + ), + port: None, + path: "/", + query: None, + fragment: None, + }: RepodataChannelConfig { + disable_bzip2: None, + disable_zstd: None, + disable_sharded: Some( + true, + ), + }, + }, + }, + concurrency: ConcurrencyConfig { + solves: 4, + downloads: 12, + }, + proxy_config: ProxyConfig { + https: Some( + Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "proxy.example.com", + ), + ), + port: Some( + 8080, + ), + path: "/", + query: None, + fragment: None, + }, + ), + http: Some( + Url { + scheme: "http", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "proxy.example.com", + ), + ), + port: Some( + 8080, + ), + path: "/", + query: None, + fragment: None, + }, + ), + non_proxy_hosts: [ + "localhost", + "127.0.0.1", + ], + }, + s3_options: S3OptionsMap( + { + "my-bucket": S3Options { + endpoint_url: Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "my-s3-host", + ), + ), + port: None, + path: "/", + query: None, + fragment: None, + }, + region: "us-east-1", + force_path_style: true, + }, + }, + ), + index_config: IndexConfig { + default: IndexChannelConfig { + write_zst: Some( + true, + ), + write_shards: Some( + false, + ), + repodata_revisions: None, + package_revision_assignment: None, + base_url: None, + channel_relations: None, + }, + per_channel: {}, + }, + run_post_link_scripts: Some( + Insecure, + ), + allow_symbolic_links: Some( + true, + ), + allow_hard_links: Some( + false, + ), + allow_ref_links: Some( + true, + ), + }, + extensions: PixiConfig { + pinning_strategy: Some( + NoPin, + ), + pypi_config: PyPIConfig { + index_url: Some( + Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "pypi.org", + ), + ), + port: None, + path: "/simple", + query: None, + fragment: None, + }, + ), + extra_index_urls: [ + Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "example.com", + ), + ), + port: None, + path: "/simple", + query: None, + fragment: None, + }, + ], + keyring_provider: Some( + Subprocess, + ), + allow_insecure_host: [ + "localhost:8080", + ], + }, + detached_environments: Some( + Path( + "/opt/pixi/envs", + ), + ), + shell: ShellConfig { + force_activate: Some( + true, + ), + source_completion_scripts: Some( + false, + ), + change_ps1: Some( + false, + ), + }, + experimental: ExperimentalConfig { + use_environment_activation_cache: Some( + true, + ), + }, + tool_platform: Some( + Linux64, + ), + cache: CacheConfig { + root: Some( + "/shared/pixi/cache", + ), + conda_packages: Some( + "/shared/pixi/cache/pkgs", + ), + repodata: Some( + "/scratch/pixi/repodata", + ), + pypi_wheels: Some( + "/scratch/pixi/wheels", + ), + pypi_mapping: Some( + "/scratch/pixi/mapping", + ), + exec_environments: Some( + "/scratch/pixi/exec", + ), + build_tool_environments: Some( + "/scratch/pixi/build-tools", + ), + detached_environments: Some( + "/shared/pixi/envs", + ), + netfs_redirect: Never, + }, + change_ps1: None, + force_activate: None, + }, + loaded_from: [], + }, + }, +) diff --git a/crates/pixi_config/tests/snapshots/compat__parse__legacy-config.toml.snap b/crates/pixi_config/tests/snapshots/compat__parse__legacy-config.toml.snap new file mode 100644 index 0000000000..5fd94edd58 --- /dev/null +++ b/crates/pixi_config/tests/snapshots/compat__parse__legacy-config.toml.snap @@ -0,0 +1,149 @@ +--- +source: crates/pixi_config/tests/compat.rs +expression: "(unused, normalized(config))" +--- +( + { + "repodata-config.disable-jlap", + }, + Config { + inner: ConfigBase { + common: CommonConfig { + default_channels: Some( + [ + Name( + "conda-forge", + ), + ], + ), + authentication_override_file: None, + tls_no_verify: None, + tls_root_certs: Some( + System, + ), + mirrors: {}, + build: BuildConfig { + package_format: None, + }, + channel_config: ChannelConfig { + channel_alias: Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "conda.anaconda.org", + ), + ), + port: None, + path: "/", + query: None, + fragment: None, + }, + root_dir: "/root/dir", + }, + repodata_config: RepodataConfig { + default: RepodataChannelConfig { + disable_bzip2: Some( + true, + ), + disable_zstd: None, + disable_sharded: None, + }, + per_channel: {}, + }, + concurrency: ConcurrencyConfig { + solves: 2, + downloads: 50, + }, + proxy_config: ProxyConfig { + https: None, + http: None, + non_proxy_hosts: [], + }, + s3_options: S3OptionsMap( + {}, + ), + index_config: IndexConfig { + default: IndexChannelConfig { + write_zst: None, + write_shards: None, + repodata_revisions: None, + package_revision_assignment: None, + base_url: None, + channel_relations: None, + }, + per_channel: {}, + }, + run_post_link_scripts: None, + allow_symbolic_links: None, + allow_hard_links: None, + allow_ref_links: None, + }, + extensions: PixiConfig { + pinning_strategy: Some( + Minor, + ), + pypi_config: PyPIConfig { + index_url: Some( + Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "pypi.org", + ), + ), + port: None, + path: "/simple", + query: None, + fragment: None, + }, + ), + extra_index_urls: [], + keyring_provider: None, + allow_insecure_host: [], + }, + detached_environments: Some( + Boolean( + true, + ), + ), + shell: ShellConfig { + force_activate: Some( + true, + ), + source_completion_scripts: None, + change_ps1: Some( + false, + ), + }, + experimental: ExperimentalConfig { + use_environment_activation_cache: None, + }, + tool_platform: None, + cache: CacheConfig { + root: None, + conda_packages: None, + repodata: None, + pypi_wheels: None, + pypi_mapping: None, + exec_environments: None, + build_tool_environments: None, + detached_environments: None, + netfs_redirect: Auto, + }, + change_ps1: Some( + false, + ), + force_activate: Some( + true, + ), + }, + loaded_from: [], + }, + }, +) diff --git a/crates/pixi_config/tests/snapshots/compat__parse__override-layer.toml.snap b/crates/pixi_config/tests/snapshots/compat__parse__override-layer.toml.snap new file mode 100644 index 0000000000..14573c5d9d --- /dev/null +++ b/crates/pixi_config/tests/snapshots/compat__parse__override-layer.toml.snap @@ -0,0 +1,237 @@ +--- +source: crates/pixi_config/tests/compat.rs +expression: "(unused, normalized(config))" +--- +( + {}, + Config { + inner: ConfigBase { + common: CommonConfig { + default_channels: Some( + [ + Name( + "robostack", + ), + ], + ), + authentication_override_file: None, + tls_no_verify: Some( + true, + ), + tls_root_certs: None, + mirrors: { + Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "conda.anaconda.org", + ), + ), + port: None, + path: "/bioconda", + query: None, + fragment: None, + }: [ + Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "prefix.dev", + ), + ), + port: None, + path: "/bioconda", + query: None, + fragment: None, + }, + ], + }, + build: BuildConfig { + package_format: None, + }, + channel_config: ChannelConfig { + channel_alias: Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "conda.anaconda.org", + ), + ), + port: None, + path: "/", + query: None, + fragment: None, + }, + root_dir: "/root/dir", + }, + repodata_config: RepodataConfig { + default: RepodataChannelConfig { + disable_bzip2: Some( + false, + ), + disable_zstd: None, + disable_sharded: None, + }, + per_channel: { + Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "prefix.dev", + ), + ), + port: None, + path: "/", + query: None, + fragment: None, + }: RepodataChannelConfig { + disable_bzip2: None, + disable_zstd: Some( + true, + ), + disable_sharded: None, + }, + }, + }, + concurrency: ConcurrencyConfig { + solves: 9, + downloads: 50, + }, + proxy_config: ProxyConfig { + https: None, + http: None, + non_proxy_hosts: [], + }, + s3_options: S3OptionsMap( + { + "other-bucket": S3Options { + endpoint_url: Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "minio.example.com", + ), + ), + port: None, + path: "/", + query: None, + fragment: None, + }, + region: "auto", + force_path_style: false, + }, + }, + ), + index_config: IndexConfig { + default: IndexChannelConfig { + write_zst: None, + write_shards: None, + repodata_revisions: None, + package_revision_assignment: None, + base_url: None, + channel_relations: None, + }, + per_channel: {}, + }, + run_post_link_scripts: None, + allow_symbolic_links: None, + allow_hard_links: None, + allow_ref_links: None, + }, + extensions: PixiConfig { + pinning_strategy: Some( + Semver, + ), + pypi_config: PyPIConfig { + index_url: Some( + Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "test.pypi.org", + ), + ), + port: None, + path: "/simple", + query: None, + fragment: None, + }, + ), + extra_index_urls: [ + Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "extra.example.com", + ), + ), + port: None, + path: "/simple", + query: None, + fragment: None, + }, + ], + keyring_provider: None, + allow_insecure_host: [], + }, + detached_environments: Some( + Boolean( + false, + ), + ), + shell: ShellConfig { + force_activate: None, + source_completion_scripts: None, + change_ps1: Some( + true, + ), + }, + experimental: ExperimentalConfig { + use_environment_activation_cache: Some( + false, + ), + }, + tool_platform: Some( + OsxArm64, + ), + cache: CacheConfig { + root: Some( + "/other/pixi/cache", + ), + conda_packages: None, + repodata: None, + pypi_wheels: None, + pypi_mapping: None, + exec_environments: None, + build_tool_environments: None, + detached_environments: None, + netfs_redirect: Always, + }, + change_ps1: None, + force_activate: None, + }, + loaded_from: [], + }, + }, +) diff --git a/crates/pixi_config/tests/snapshots/compat__parse__snake-case-aliases.toml.snap b/crates/pixi_config/tests/snapshots/compat__parse__snake-case-aliases.toml.snap new file mode 100644 index 0000000000..58020e11db --- /dev/null +++ b/crates/pixi_config/tests/snapshots/compat__parse__snake-case-aliases.toml.snap @@ -0,0 +1,133 @@ +--- +source: crates/pixi_config/tests/compat.rs +expression: "(unused, normalized(config))" +--- +( + {}, + Config { + inner: ConfigBase { + common: CommonConfig { + default_channels: Some( + [ + Name( + "conda-forge", + ), + ], + ), + authentication_override_file: Some( + "/path/to/auth.json", + ), + tls_no_verify: Some( + true, + ), + tls_root_certs: Some( + System, + ), + mirrors: {}, + build: BuildConfig { + package_format: None, + }, + channel_config: ChannelConfig { + channel_alias: Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "conda.anaconda.org", + ), + ), + port: None, + path: "/", + query: None, + fragment: None, + }, + root_dir: "/root/dir", + }, + repodata_config: RepodataConfig { + default: RepodataChannelConfig { + disable_bzip2: Some( + true, + ), + disable_zstd: Some( + true, + ), + disable_sharded: None, + }, + per_channel: {}, + }, + concurrency: ConcurrencyConfig { + solves: 4, + downloads: 50, + }, + proxy_config: ProxyConfig { + https: None, + http: None, + non_proxy_hosts: [], + }, + s3_options: S3OptionsMap( + {}, + ), + index_config: IndexConfig { + default: IndexChannelConfig { + write_zst: None, + write_shards: None, + repodata_revisions: None, + package_revision_assignment: None, + base_url: None, + channel_relations: None, + }, + per_channel: {}, + }, + run_post_link_scripts: None, + allow_symbolic_links: Some( + false, + ), + allow_hard_links: Some( + true, + ), + allow_ref_links: Some( + false, + ), + }, + extensions: PixiConfig { + pinning_strategy: None, + pypi_config: PyPIConfig { + index_url: None, + extra_index_urls: [], + keyring_provider: None, + allow_insecure_host: [], + }, + detached_environments: None, + shell: ShellConfig { + force_activate: None, + source_completion_scripts: None, + change_ps1: Some( + false, + ), + }, + experimental: ExperimentalConfig { + use_environment_activation_cache: None, + }, + tool_platform: None, + cache: CacheConfig { + root: None, + conda_packages: None, + repodata: None, + pypi_wheels: None, + pypi_mapping: None, + exec_environments: None, + build_tool_environments: None, + detached_environments: None, + netfs_redirect: Auto, + }, + change_ps1: Some( + false, + ), + force_activate: None, + }, + loaded_from: [], + }, + }, +) diff --git a/crates/pixi_config/tests/snapshots/compat__parse__typos.toml.snap b/crates/pixi_config/tests/snapshots/compat__parse__typos.toml.snap new file mode 100644 index 0000000000..230e1cf31a --- /dev/null +++ b/crates/pixi_config/tests/snapshots/compat__parse__typos.toml.snap @@ -0,0 +1,121 @@ +--- +source: crates/pixi_config/tests/compat.rs +expression: "(unused, normalized(config))" +--- +( + { + "authentification-override-file", + "concurrency.solvs", + "pinning-strateggy", + "pypi-config.index-urll", + "shell.chnge-ps1", + }, + Config { + inner: ConfigBase { + common: CommonConfig { + default_channels: Some( + [ + Name( + "conda-forge", + ), + ], + ), + authentication_override_file: None, + tls_no_verify: None, + tls_root_certs: None, + mirrors: {}, + build: BuildConfig { + package_format: None, + }, + channel_config: ChannelConfig { + channel_alias: Url { + scheme: "https", + cannot_be_a_base: false, + username: "", + password: None, + host: Some( + Domain( + "conda.anaconda.org", + ), + ), + port: None, + path: "/", + query: None, + fragment: None, + }, + root_dir: "/root/dir", + }, + repodata_config: RepodataConfig { + default: RepodataChannelConfig { + disable_bzip2: None, + disable_zstd: None, + disable_sharded: None, + }, + per_channel: {}, + }, + concurrency: ConcurrencyConfig { + solves: 4, + downloads: 8, + }, + proxy_config: ProxyConfig { + https: None, + http: None, + non_proxy_hosts: [], + }, + s3_options: S3OptionsMap( + {}, + ), + index_config: IndexConfig { + default: IndexChannelConfig { + write_zst: None, + write_shards: None, + repodata_revisions: None, + package_revision_assignment: None, + base_url: None, + channel_relations: None, + }, + per_channel: {}, + }, + run_post_link_scripts: None, + allow_symbolic_links: None, + allow_hard_links: None, + allow_ref_links: None, + }, + extensions: PixiConfig { + pinning_strategy: None, + pypi_config: PyPIConfig { + index_url: None, + extra_index_urls: [], + keyring_provider: None, + allow_insecure_host: [], + }, + detached_environments: None, + shell: ShellConfig { + force_activate: Some( + true, + ), + source_completion_scripts: None, + change_ps1: None, + }, + experimental: ExperimentalConfig { + use_environment_activation_cache: None, + }, + tool_platform: None, + cache: CacheConfig { + root: None, + conda_packages: None, + repodata: None, + pypi_wheels: None, + pypi_mapping: None, + exec_environments: None, + build_tool_environments: None, + detached_environments: None, + netfs_redirect: Auto, + }, + change_ps1: None, + force_activate: None, + }, + loaded_from: [], + }, + }, +) From 1b03516cf8e02b80737a50ac51f0ab5c2ce85a18 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 6 Jul 2026 09:02:28 +0000 Subject: [PATCH 3/5] test(pixi_config): make compat parse snapshots machine-independent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The parse snapshots embedded the concurrency.solves default, which is the local CPU count, so fixtures that don't set [concurrency] (e.g. snake-case-aliases.toml) produced snapshots that only passed on the machine that generated them. Normalize solves unconditionally in the snapshot helper — a conditional "only when equal to the default" would flip whenever an explicitly configured value happens to match the CPU count — and assert the explicitly configured values in code instead, where they are deterministic. Verified by running the suite pinned to a different CPU count (taskset). Same fix applied to the rattler_config catalog upstream (conda/rattler#2557). Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01EzYs4p6XJDj9QBcNB4ipR7 --- crates/pixi_config/tests/compat.rs | 25 ++++++++++++++++--- .../compat__parse__kitchen-sink.toml.snap | 2 +- .../compat__parse__legacy-config.toml.snap | 2 +- .../compat__parse__override-layer.toml.snap | 2 +- ...ompat__parse__snake-case-aliases.toml.snap | 2 +- .../snapshots/compat__parse__typos.toml.snap | 2 +- 6 files changed, 27 insertions(+), 8 deletions(-) diff --git a/crates/pixi_config/tests/compat.rs b/crates/pixi_config/tests/compat.rs index afa3cc3a9d..cf01f0fe4f 100644 --- a/crates/pixi_config/tests/compat.rs +++ b/crates/pixi_config/tests/compat.rs @@ -39,14 +39,33 @@ fn parse(name: &str) -> (Config, BTreeSet) { .unwrap_or_else(|e| panic!("{name} must parse: {e}")) } -/// `channel_config` is not part of the TOML schema (serde-skipped) and its -/// default embeds the current working directory; pin it to a fixed path so -/// snapshots are machine-independent. +/// Strip machine-dependent values before snapshotting: `channel_config` +/// is serde-skipped and its default embeds the current working directory, +/// and `concurrency.solves` defaults to the local CPU count. `solves` is +/// normalized *unconditionally* (a conditional "only when it equals the +/// default" would flip whenever an explicitly configured value happens to +/// match the CPU count); explicitly configured values are asserted in +/// `explicit_concurrency_values_parse` instead. fn normalized(mut config: Config) -> Config { config.channel_config = ChannelConfig::default_with_root_dir(PathBuf::from("/root/dir")); + config.concurrency.solves = 0; config } +/// Explicitly configured concurrency values parse correctly. Kept out of +/// the snapshots because `normalized` blanks `solves` (see there). +#[test] +fn explicit_concurrency_values_parse() { + let (config, _) = parse("kitchen-sink.toml"); + assert_eq!(config.concurrency.solves, 4); + + let (config, _) = parse("legacy-config.toml"); + assert_eq!(config.concurrency.solves, 2); + + let (config, _) = parse("override-layer.toml"); + assert_eq!(config.concurrency.solves, 9); +} + const FIXTURES: &[&str] = &[ "kitchen-sink.toml", "snake-case-aliases.toml", diff --git a/crates/pixi_config/tests/snapshots/compat__parse__kitchen-sink.toml.snap b/crates/pixi_config/tests/snapshots/compat__parse__kitchen-sink.toml.snap index 0da6131aef..853bdb868b 100644 --- a/crates/pixi_config/tests/snapshots/compat__parse__kitchen-sink.toml.snap +++ b/crates/pixi_config/tests/snapshots/compat__parse__kitchen-sink.toml.snap @@ -137,7 +137,7 @@ expression: "(unused, normalized(config))" }, }, concurrency: ConcurrencyConfig { - solves: 4, + solves: 0, downloads: 12, }, proxy_config: ProxyConfig { diff --git a/crates/pixi_config/tests/snapshots/compat__parse__legacy-config.toml.snap b/crates/pixi_config/tests/snapshots/compat__parse__legacy-config.toml.snap index 5fd94edd58..1a8b6239ed 100644 --- a/crates/pixi_config/tests/snapshots/compat__parse__legacy-config.toml.snap +++ b/crates/pixi_config/tests/snapshots/compat__parse__legacy-config.toml.snap @@ -54,7 +54,7 @@ expression: "(unused, normalized(config))" per_channel: {}, }, concurrency: ConcurrencyConfig { - solves: 2, + solves: 0, downloads: 50, }, proxy_config: ProxyConfig { diff --git a/crates/pixi_config/tests/snapshots/compat__parse__override-layer.toml.snap b/crates/pixi_config/tests/snapshots/compat__parse__override-layer.toml.snap index 14573c5d9d..b878c5ee25 100644 --- a/crates/pixi_config/tests/snapshots/compat__parse__override-layer.toml.snap +++ b/crates/pixi_config/tests/snapshots/compat__parse__override-layer.toml.snap @@ -106,7 +106,7 @@ expression: "(unused, normalized(config))" }, }, concurrency: ConcurrencyConfig { - solves: 9, + solves: 0, downloads: 50, }, proxy_config: ProxyConfig { diff --git a/crates/pixi_config/tests/snapshots/compat__parse__snake-case-aliases.toml.snap b/crates/pixi_config/tests/snapshots/compat__parse__snake-case-aliases.toml.snap index 58020e11db..919d237abf 100644 --- a/crates/pixi_config/tests/snapshots/compat__parse__snake-case-aliases.toml.snap +++ b/crates/pixi_config/tests/snapshots/compat__parse__snake-case-aliases.toml.snap @@ -58,7 +58,7 @@ expression: "(unused, normalized(config))" per_channel: {}, }, concurrency: ConcurrencyConfig { - solves: 4, + solves: 0, downloads: 50, }, proxy_config: ProxyConfig { diff --git a/crates/pixi_config/tests/snapshots/compat__parse__typos.toml.snap b/crates/pixi_config/tests/snapshots/compat__parse__typos.toml.snap index 230e1cf31a..371cd3737d 100644 --- a/crates/pixi_config/tests/snapshots/compat__parse__typos.toml.snap +++ b/crates/pixi_config/tests/snapshots/compat__parse__typos.toml.snap @@ -54,7 +54,7 @@ expression: "(unused, normalized(config))" per_channel: {}, }, concurrency: ConcurrencyConfig { - solves: 4, + solves: 0, downloads: 8, }, proxy_config: ProxyConfig { From 5985d9c410e8862e5805719b9b66859379b28c57 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 10 Jul 2026 12:02:24 +0000 Subject: [PATCH 4/5] build(deps): use released rattler 0.47/0.6 + rattler-build main git dep Now that rattler-build's config PR (prefix-dev/rattler-build#2636) is merged, align pixi's rattler/rattler-build sources so the shared rattler_config / rattler_conda_types types unify: - Drop the conda/rattler [patch.crates-io] block. It pinned the pre-release rattler_config 0.5.2 / rattler 0.46 branch, which conflicts with rattler-build main (built against the released rattler_config 0.6 / rattler 0.47). rattler_config 0.6 is now released, so the patch is obsolete. - Bump rattler requirements to the released set: rattler 0.47, rattler_conda_types 0.48, rattler_config 0.6, rattler_repodata_gateway 0.30. - Patch all rattler-build crates in the tree to prefix-dev/rattler-build main (the merged config update); the crates.io rattler_build_core 0.2.8 still pins the old rattler 0.46 and is unusable until a new release is published. Lockfile re-resolved: a single copy of each shared crate from crates.io, rattler-build crates from git main, no leftover conda/rattler refs. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01EzYs4p6XJDj9QBcNB4ipR7 --- Cargo.lock | 1611 +++++++++++++++++++++------------------------------- Cargo.toml | 49 +- 2 files changed, 676 insertions(+), 984 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd6ca3aa1b..34196daa98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,11 +30,11 @@ dependencies = [ [[package]] name = "aes" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66bd29a732b644c0431c6140f370d097879203d79b80c94a6747ba0872adaef8" +checksum = "f1fc76eaeac4c9164506c466d4ffdd8ec9d0c5bf57ee97177c4d8eceb3a0e138" dependencies = [ - "cipher 0.5.1", + "cipher 0.5.2", "cpubits", "cpufeatures 0.3.0", ] @@ -161,9 +161,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "apple-native-keyring-store" @@ -178,9 +178,9 @@ dependencies = [ [[package]] name = "arborium" -version = "2.17.0" +version = "2.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66464d43ce8ad5a81f59a9dac02d33dfe384e8fe9cd334fc607a0b81699d2594" +checksum = "abb7a99c146e42da48d5783335814d9bd0f088143aa51fb5ea5b59855df5ca70" dependencies = [ "arborium-highlight", "arborium-theme", @@ -191,9 +191,9 @@ dependencies = [ [[package]] name = "arborium-highlight" -version = "2.17.0" +version = "2.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3e19dccfe05568006e5919b0e157695fb4c90a6a4c07582b51454e0c85c4365" +checksum = "65635c663883cb887d52abce06650f81e4abeb7bfd8e79a555f6a0d8e8f0a31b" dependencies = [ "arborium-theme", "arborium-tree-sitter", @@ -202,9 +202,9 @@ dependencies = [ [[package]] name = "arborium-sysroot" -version = "2.17.0" +version = "2.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "260e0358abe4ede3af8b4df7a311bc9b6e4a60e4bd50af16deddfcd13759a908" +checksum = "59d99d80550b726f9dec7ee6d07118c31e08b10e729ac488eabd4c10603dc841" dependencies = [ "cc", "dlmalloc", @@ -212,15 +212,15 @@ dependencies = [ [[package]] name = "arborium-theme" -version = "2.17.0" +version = "2.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747d16e6679f93cd84e7a9e8e47bec0055eb900fd3caaa3f3c2bbb31286e6c8d" +checksum = "a00a8f02b994f454d9703dd6a8b6075ba778320550d699198faff1882594c0f7" [[package]] name = "arborium-toml" -version = "2.17.0" +version = "2.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2719568f38f8a6635b21258cff7860cd549ae57c84c29e1dec041c0e6317ab75" +checksum = "102a80466c8afd64c0c05c57cae30e5ff5ddbf3f943065fdd8fbe64331b49952" dependencies = [ "arborium-sysroot", "cc", @@ -229,9 +229,9 @@ dependencies = [ [[package]] name = "arborium-tree-sitter" -version = "2.17.0" +version = "2.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4879b6a79798d45d29d54bf000fd4d1b88a8e654e0b0cb762ac402944129233b" +checksum = "b27f3bd6bb7192e4a19dc177748532b305e9052839b34e55705f53e5eea2d5ca" dependencies = [ "arborium-sysroot", "cc", @@ -241,6 +241,15 @@ dependencies = [ "tree-sitter-language", ] +[[package]] +name = "arc-swap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b" +dependencies = [ + "rustversion", +] + [[package]] name = "archspec" version = "0.2.0" @@ -269,9 +278,9 @@ checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" [[package]] name = "arrayvec" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" [[package]] name = "arwen-codesign" @@ -287,9 +296,9 @@ dependencies = [ [[package]] name = "asn1-rs" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60" +checksum = "b7f43a50ac4fdca5df8e885c21b835997f0a1cdee65494a6847694a98652d9d8" dependencies = [ "asn1-rs-derive", "asn1-rs-impl", @@ -371,7 +380,7 @@ dependencies = [ "futures", "getrandom 0.2.17", "http 1.4.2", - "hyper 1.9.0", + "hyper 1.10.1", "reqwest", "retry-policies", "thiserror 2.0.18", @@ -391,15 +400,15 @@ dependencies = [ [[package]] name = "astral-tokio-tar" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb50a7aae84a03bf55b067832bc376f4961b790c97e64d3eacee97d389b90277" +checksum = "08648fef353ab39a9d26f909ad53fc4f071be4c91853b78523f5cc3d9e5ebffd" dependencies = [ - "filetime", "futures-core", "libc", "portable-atomic", "rustc-hash", + "rustix 0.38.44", "tokio", "tokio-stream", "xattr", @@ -424,7 +433,7 @@ dependencies = [ "futures", "http-content-range", "itertools 0.14.0", - "memmap2 0.9.10", + "memmap2 0.9.11", "reqwest", "thiserror 2.0.18", "tokio", @@ -551,15 +560,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "aws-config" -version = "1.8.16" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f156acdd2cf55f5aa53ee416c4ac851cf1222694506c0b1f78c85695e9ca9d" +checksum = "47712fde1909402600ccfbb26e47d482d2e58bb9e9e603d9f17e67cc435a6319" dependencies = [ "aws-credential-types", "aws-runtime", @@ -572,6 +581,7 @@ dependencies = [ "aws-smithy-json", "aws-smithy-runtime", "aws-smithy-runtime-api", + "aws-smithy-schema", "aws-smithy-types", "aws-types", "base64-simd", @@ -579,7 +589,7 @@ dependencies = [ "fastrand", "hex", "http 1.4.2", - "p256 0.13.2", + "p256", "rand 0.8.6", "sha1 0.10.6", "sha2 0.10.9", @@ -593,9 +603,9 @@ dependencies = [ [[package]] name = "aws-credential-types" -version = "1.2.14" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f20799b373a1be121fe3005fba0c2090af9411573878f224df44b42727fcaf7" +checksum = "e93964ffdaf57857f544be3666a5f57570bb699e934700f11b49708f61bb556e" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -605,9 +615,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" +checksum = "4342d8937fc7e5dd9b1c60292261c0670c882a2cd1719cfc11b1af41731e32ad" dependencies = [ "aws-lc-sys", "untrusted 0.7.1", @@ -616,21 +626,22 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.41.0" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" +checksum = "6d9ceb1da931507a12f4fccea479dccd00da1943e1b4ae72d8e502d707361444" dependencies = [ "cc", "cmake", "dunce", "fs_extra", + "pkg-config", ] [[package]] name = "aws-runtime" -version = "1.7.3" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dcd93c82209ac7413532388067dce79be5a8780c1786e5fae3df22e4dee2864" +checksum = "7816e98ee912159f45d307e5ee6bfea4a335a55aee15f7f3e32f81a6f3000f1d" dependencies = [ "aws-credential-types", "aws-sigv4", @@ -656,10 +667,11 @@ dependencies = [ [[package]] name = "aws-sdk-s3" -version = "1.132.0" +version = "1.138.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5575840a3a6b11f6011463ebe359320dfe5b67babb5e9b06fed6ddf809a9ab40" +checksum = "7c29be98554a0deea25d4eaca131240a224dcbcaf20357e35cc432e17b721ab5" dependencies = [ + "arc-swap", "aws-credential-types", "aws-runtime", "aws-sigv4", @@ -671,6 +683,7 @@ dependencies = [ "aws-smithy-observability", "aws-smithy-runtime", "aws-smithy-runtime-api", + "aws-smithy-schema", "aws-smithy-types", "aws-smithy-xml", "aws-types", @@ -691,10 +704,11 @@ dependencies = [ [[package]] name = "aws-sdk-signin" -version = "1.9.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c8ee580b0c24a1e16e63efc2d96d0d0e6f9ecfd397818467d247b628a7cad5" +checksum = "0fff6102ab555e20bda506f8878fce0e786a936f2821fd32840ea89c3120baf6" dependencies = [ + "arc-swap", "aws-credential-types", "aws-runtime", "aws-smithy-async", @@ -703,6 +717,7 @@ dependencies = [ "aws-smithy-observability", "aws-smithy-runtime", "aws-smithy-runtime-api", + "aws-smithy-schema", "aws-smithy-types", "aws-types", "bytes", @@ -715,10 +730,11 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.98.0" +version = "1.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d69c77aafa20460c68b6b3213c84f6423b6e76dbf89accd3e1789a686ffd9489" +checksum = "0469f435f645ad2162cfb463b15bde37115966ee3acf2d87fb4871ee309b8401" dependencies = [ + "arc-swap", "aws-credential-types", "aws-runtime", "aws-smithy-async", @@ -727,6 +743,7 @@ dependencies = [ "aws-smithy-observability", "aws-smithy-runtime", "aws-smithy-runtime-api", + "aws-smithy-schema", "aws-smithy-types", "aws-types", "bytes", @@ -739,10 +756,11 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.100.0" +version = "1.105.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7e7b09346d5ca22a2a08267555843a6a0127fb20d8964cb6ecfb8fdb190225" +checksum = "085faefb253f770655e162b9304321e62a1e71adf7f019ee1f4454228a377b3a" dependencies = [ + "arc-swap", "aws-credential-types", "aws-runtime", "aws-smithy-async", @@ -751,6 +769,7 @@ dependencies = [ "aws-smithy-observability", "aws-smithy-runtime", "aws-smithy-runtime-api", + "aws-smithy-schema", "aws-smithy-types", "aws-types", "bytes", @@ -763,10 +782,11 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.103.0" +version = "1.108.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2249b81a2e73a8027c41c378463a81ec39b8510f184f2caab87de912af0f49b" +checksum = "3c72b08911d8128dd360fe1b22a9fec0fa8b552dde8ec828dcf20ef5ec974e9f" dependencies = [ + "arc-swap", "aws-credential-types", "aws-runtime", "aws-smithy-async", @@ -776,6 +796,7 @@ dependencies = [ "aws-smithy-query", "aws-smithy-runtime", "aws-smithy-runtime-api", + "aws-smithy-schema", "aws-smithy-types", "aws-smithy-xml", "aws-types", @@ -788,9 +809,9 @@ dependencies = [ [[package]] name = "aws-sigv4" -version = "1.4.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68dc0b907359b120170613b5c09ccc61304eac3998ff6274b97d93ee6490115a" +checksum = "723c2234ad7511ceef63eab016b7ba6ff7c55590fefb96fa8467af014a07309f" dependencies = [ "aws-credential-types", "aws-smithy-eventstream", @@ -798,15 +819,14 @@ dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", "bytes", - "crypto-bigint 0.5.5", + "crypto-bigint", "form_urlencoded", "hex", "hmac 0.13.0", "http 0.2.12", "http 1.4.2", - "p256 0.11.1", + "p256", "percent-encoding", - "ring", "sha2 0.11.0", "subtle", "time", @@ -816,9 +836,9 @@ dependencies = [ [[package]] name = "aws-smithy-async" -version = "1.2.14" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffcaf626bdda484571968400c326a244598634dc75fd451325a54ad1a59acfc" +checksum = "f02e407fb3b54891734224b9ffac8a71fdd35f542500fa1af95754a6b2beb316" dependencies = [ "futures-util", "pin-project-lite", @@ -827,9 +847,9 @@ dependencies = [ [[package]] name = "aws-smithy-checksums" -version = "0.64.7" +version = "0.65.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10efbbcec1e044b81600e2fc562a391951d291152d95b482d5b7e7132299d762" +checksum = "b67ecd999972b58e67cab052f5129906c08c25883bd0788ceefc55ef97d61307" dependencies = [ "aws-smithy-http", "aws-smithy-types", @@ -848,9 +868,9 @@ dependencies = [ [[package]] name = "aws-smithy-eventstream" -version = "0.60.20" +version = "0.61.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf09d74e5e32f76b8762da505a3cd59303e367a664ca67295387baa8c1d7548" +checksum = "5a9381123ab62d20c13082b151f30f962a3b112b727345394536dfa39a482944" dependencies = [ "aws-smithy-types", "bytes", @@ -859,9 +879,9 @@ dependencies = [ [[package]] name = "aws-smithy-http" -version = "0.63.6" +version = "0.64.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1ab2dc1c2c3749ead27180d333c42f11be8b0e934058fb4b2258ee8dbe5231" +checksum = "37843d9add67c3aff5856f409c6dc315d3cdff60f9c0cb5b670dab1e9920306d" dependencies = [ "aws-smithy-eventstream", "aws-smithy-runtime-api", @@ -881,16 +901,16 @@ dependencies = [ [[package]] name = "aws-smithy-http-client" -version = "1.1.12" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a2f165a7feee6f263028b899d0a181987f4fa7179a6411a32a439fba7c5f769" +checksum = "635d23afda0a6ab48d666c4d447c4873e8d1e83518a2be2093122397e50b838e" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", "aws-smithy-types", "h2", "http 1.4.2", - "hyper 1.9.0", + "hyper 1.10.1", "hyper-rustls", "hyper-util", "pin-project-lite", @@ -905,27 +925,29 @@ dependencies = [ [[package]] name = "aws-smithy-json" -version = "0.62.5" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9648b0bb82a2eedd844052c6ad2a1a822d1f8e3adee5fbf668366717e428856a" +checksum = "3dc65a121adb4b33729919fcfa14fa36fb33c1555a8f06bb0e2188dbfdc1d9ef" dependencies = [ + "aws-smithy-runtime-api", + "aws-smithy-schema", "aws-smithy-types", ] [[package]] name = "aws-smithy-observability" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06c2315d173edbf1920da8ba3a7189695827002e4c0fc961973ab1c54abca9c" +checksum = "8e86338c869539a581bf161247762a6e87f92c5c075060057b5ed6d06632ed0c" dependencies = [ "aws-smithy-runtime-api", ] [[package]] name = "aws-smithy-query" -version = "0.60.15" +version = "0.61.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a56d79744fb3edb5d722ef79d86081e121d3b9422cb209eb03aea6aa4f21ebd" +checksum = "dd22a6ba36e3f113cb8d5b3d1fe0ed31c76ee608ef63322d753bb8d2c9479e77" dependencies = [ "aws-smithy-types", "urlencoding", @@ -933,15 +955,16 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0504b1ab12debb5959e5165ee5fe97dd387e7aa7ea6a477bfd7635dfe769a4f5" +checksum = "bea94a9ff8464016338c851e24b472d7131c388c88898a502e781815b2ee6045" dependencies = [ "aws-smithy-async", "aws-smithy-http", "aws-smithy-http-client", "aws-smithy-observability", "aws-smithy-runtime-api", + "aws-smithy-schema", "aws-smithy-types", "bytes", "fastrand", @@ -958,9 +981,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71a13df6ada0aafbf21a73bdfcdf9324cfa9df77d96b8446045be3cde61b42e" +checksum = "22ed1ebe6e0a95ea84570225f5a8208dec4b8f77e61a9b0d6f51773fcb4612f0" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api-macros", @@ -976,20 +999,31 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api-macros" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d7396fd9500589e62e460e987ecb671bad374934e55ec3b5f498cc7a8a8a7b7" +checksum = "221eaa237ddf1ca79b60d1372aad77e47f9c0ea5b3ce5099da8c61d027dc77b3" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "aws-smithy-schema" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d56e0a4e53127a632224e43633b0fe045fa9e1e3cfc68b9830f1115e103f910" +dependencies = [ + "aws-smithy-runtime-api", + "aws-smithy-types", + "http 1.4.2", +] + [[package]] name = "aws-smithy-types" -version = "1.4.7" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d73dbfbaa8e4bc57b9045137680b958d274823509a360abfd8e1d514d40c95c" +checksum = "d6dc683efb34b9e755675b37fedbe0103141e5b6df7bdc9eb6967756a8c167d8" dependencies = [ "base64-simd", "bytes", @@ -1013,22 +1047,26 @@ dependencies = [ [[package]] name = "aws-smithy-xml" -version = "0.60.15" +version = "0.61.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce02add1aa3677d022f8adf81dcbe3046a95f17a1b1e8979c145cd21d3d22b3" +checksum = "ea3f68eec3607f02acd24067969ce2abc6ba16aa7d5ce59ca450ed2fb5f78957" dependencies = [ + "aws-smithy-runtime-api", + "aws-smithy-schema", + "aws-smithy-types", "xmlparser", ] [[package]] name = "aws-types" -version = "1.3.15" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4bbcaa9304ea40902d3d5f42a0428d1bd895a2b0f6999436fb279ffddc58ac" +checksum = "e957a6c6dbce82b7a91f44231c09273159703769f447cbe85e854dfe9cf67f86" dependencies = [ "aws-credential-types", "aws-smithy-async", "aws-smithy-runtime-api", + "aws-smithy-schema", "aws-smithy-types", "rustc_version", "tracing", @@ -1047,7 +1085,7 @@ dependencies = [ "http 1.4.2", "http-body 1.0.1", "http-body-util", - "hyper 1.9.0", + "hyper 1.10.1", "hyper-util", "itoa", "matchit", @@ -1130,12 +1168,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - [[package]] name = "base16ct" version = "0.2.0" @@ -1193,15 +1225,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" [[package]] name = "bitvec" -version = "1.0.1" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" dependencies = [ "funty", "radium", @@ -1238,9 +1270,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" dependencies = [ "hybrid-array", ] @@ -1295,20 +1327,20 @@ dependencies = [ [[package]] name = "bstr" -version = "1.12.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +checksum = "5cee35f73844aa3014bb606320a6c1f010249dbdf43342fe54b5a4f6a8ed4b79" dependencies = [ "memchr", - "regex-automata 0.4.14", - "serde", + "regex-automata 0.4.15", + "serde_core", ] [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytecheck" @@ -1341,9 +1373,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" dependencies = [ "serde", ] @@ -1421,9 +1453,9 @@ checksum = "1bf2a5fb3207c12b5d208ebc145f967fea5cac41a021c37417ccc31ba40f39ee" [[package]] name = "cargo-util" -version = "0.2.28" +version = "0.2.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4162900cab52029d1e29a44ba98277ec9936948b8cefbd7a2269c990ac7d58a" +checksum = "5d7123d293f652da25899a771e48756075710465b2eedb0fc35aa3b368e9cf5c" dependencies = [ "anyhow", "core-foundation 0.10.1", @@ -1433,8 +1465,9 @@ dependencies = [ "jobserver", "libc", "miow", + "portable-atomic", "same-file", - "sha2 0.10.9", + "sha2 0.11.0", "shell-escape", "tempfile", "tracing", @@ -1463,23 +1496,23 @@ dependencies = [ [[package]] name = "cbc" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98db6aeaef0eeef2c1e3ce9a27b739218825dae116076352ac3777076aa22225" +checksum = "ce2dc9ee5f88d11e0beb842c88b33c8a5cf0d1329c4b19494af42b07dbfe8896" dependencies = [ - "cipher 0.5.1", + "cipher 0.5.2", ] [[package]] name = "cc" -version = "1.2.62" +version = "1.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" +checksum = "f5d6cac793997bd970000024b2934968efe83b382de4fdcf4fcb46b6ee4ad996" dependencies = [ "find-msvc-tools", "jobserver", "libc", - "shlex 1.3.0", + "shlex", ] [[package]] @@ -1508,9 +1541,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chacha20" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" dependencies = [ "cfg-if 1.0.4", "cpufeatures 0.3.0", @@ -1553,11 +1586,11 @@ dependencies = [ [[package]] name = "cipher" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34d8227fe1ba289043aeb13792056ff80fd6de1a9f49137a5f499de8e8c78ea" +checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c" dependencies = [ - "crypto-common 0.2.1", + "crypto-common 0.2.2", "inout 0.2.2", ] @@ -1597,9 +1630,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.6.5" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7a9bfdb35811f9e59832f0f05975114d2251b415fb534108e6f34060fd772" +checksum = "db8b397918185f0161ff3d6fcaa9e4bfc09b8367caf6e1d4a2848e5477ed027b" dependencies = [ "clap", ] @@ -1643,9 +1676,9 @@ dependencies = [ [[package]] name = "cmov" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" [[package]] name = "cmp_any" @@ -1660,8 +1693,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "961b955a666e25ee5a1091d219128d6e6401e3dab84efb1a2bf6b4035d797b39" dependencies = [ "crmf", - "der 0.7.10", - "spki 0.7.3", + "der", + "spki", "x509-cert", ] @@ -1672,15 +1705,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b77c319abfd5219629c45c34c89ba945ed3c5e49fcde9d16b6c3885f118a730" dependencies = [ "const-oid 0.9.6", - "der 0.7.10", - "spki 0.7.3", + "der", + "spki", "x509-cert", ] [[package]] name = "coalesced_map" version = "0.1.3" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fe09392885c9af28aed39c6ddd06e41b43dbe98a850ccf0abe3f88d7cc75de" dependencies = [ "dashmap", "tokio", @@ -1735,15 +1769,15 @@ dependencies = [ [[package]] name = "configparser" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57e3272f0190c3f1584272d613719ba5fc7df7f4942fe542e63d949cf3a649b" +checksum = "b46dec724fd22199ebde05033a0cbae453bc3b1ecff11eb6a6bb3eec4b90c6a4" [[package]] name = "console" -version = "0.16.3" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" +checksum = "4fe5f465a4f6fee88fad41b85d990f84c835335e85b5d9e6e63e0d06d28cba7c" dependencies = [ "encode_unicode", "libc", @@ -1891,30 +1925,13 @@ dependencies = [ "libc", ] -[[package]] -name = "crc" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" - [[package]] name = "crc-fast" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd92aca2c6001b1bf5ba0ff84ee74ec8501b52bbef0cac80bf25a6c1d87a83d" +checksum = "e75b2483e97a5a7da73ac68a05b629f9c53cff58d8ed1c77866079e18b00dba5" dependencies = [ - "crc", "digest 0.10.7", - "rustversion", "spin 0.10.0", ] @@ -1943,25 +1960,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36fe21b96d5b87f5de4b5b7202ec41c00110ac817ce6728fe75fb2fe5962ed92" dependencies = [ "cms", - "der 0.7.10", - "spki 0.7.3", + "der", + "spki", "x509-cert", ] [[package]] name = "crossbeam-channel" -version = "0.5.15" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -1969,18 +1986,18 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "crossterm" @@ -1988,7 +2005,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "crossterm_winapi", "document-features", "parking_lot 0.12.5", @@ -2011,18 +2028,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" -[[package]] -name = "crypto-bigint" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - [[package]] name = "crypto-bigint" version = "0.5.5" @@ -2047,9 +2052,9 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ "hybrid-array", ] @@ -2213,9 +2218,9 @@ checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] name = "dbus" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b942602992bb7acfd1f51c49811c58a610ef9181b6e66f3e519d79b540a3bf73" +checksum = "3ab69f03cc8c4340c9c8e315114e1658e6775a9b16a04357973aa21cec22b32e" dependencies = [ "libc", "libdbus-sys", @@ -2253,9 +2258,9 @@ dependencies = [ [[package]] name = "defmt" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6e524506490a1953d237cb87b1cfc1e46f88c18f10a22dfe0f507dc6bfc7f7f" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" dependencies = [ "bitflags 1.3.2", "defmt-macros", @@ -2263,12 +2268,11 @@ dependencies = [ [[package]] name = "defmt-macros" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a27770e9c8f719a79d8b638281f4d828f77d8fd61e0bd94451b9b85e576a0b" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" dependencies = [ "defmt-parser", - "proc-macro-error2", "proc-macro2", "quote", "syn", @@ -2320,12 +2324,11 @@ dependencies = [ [[package]] name = "deno_task_shell" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5724630e5d004297ca84920ef90cbf8a5459b06f8cd553e1a75d9f3ad5cd6fd" +checksum = "bd069c87eb3cdc25e9898fe633a07ec7f20218e92ad3e7eccab3db324764d4fb" dependencies = [ - "anyhow", - "bitflags 2.11.1", + "bitflags 2.13.0", "deno_path_util", "futures", "glob", @@ -2339,16 +2342,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "der" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" -dependencies = [ - "const-oid 0.9.6", - "zeroize", -] - [[package]] name = "der" version = "0.7.10" @@ -2393,7 +2386,6 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ - "powerfmt", "serde_core", ] @@ -2450,9 +2442,9 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ - "block-buffer 0.12.0", + "block-buffer 0.12.1", "const-oid 0.10.2", - "crypto-common 0.2.1", + "crypto-common 0.2.2", "ctutils", ] @@ -2492,7 +2484,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "libc", "objc2", @@ -2500,9 +2492,9 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", @@ -2556,30 +2548,18 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" -[[package]] -name = "ecdsa" -version = "0.14.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" -dependencies = [ - "der 0.6.1", - "elliptic-curve 0.12.3", - "rfc6979 0.3.1", - "signature 1.6.4", -] - [[package]] name = "ecdsa" version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "der 0.7.10", + "der", "digest 0.10.7", - "elliptic-curve 0.13.8", - "rfc6979 0.4.0", - "signature 2.2.0", - "spki 0.7.3", + "elliptic-curve", + "rfc6979", + "signature", + "spki", ] [[package]] @@ -2588,8 +2568,8 @@ version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ - "pkcs8 0.10.2", - "signature 2.2.0", + "pkcs8", + "signature", ] [[package]] @@ -2608,29 +2588,9 @@ dependencies = [ [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "elliptic-curve" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" -dependencies = [ - "base16ct 0.1.1", - "crypto-bigint 0.4.9", - "der 0.6.1", - "digest 0.10.7", - "ff 0.12.1", - "generic-array", - "group 0.12.1", - "pkcs8 0.9.0", - "rand_core 0.6.4", - "sec1 0.3.0", - "subtle", - "zeroize", -] +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "elliptic-curve" @@ -2638,17 +2598,17 @@ version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ - "base16ct 0.2.0", - "crypto-bigint 0.5.5", + "base16ct", + "crypto-bigint", "digest 0.10.7", - "ff 0.13.1", + "ff", "generic-array", - "group 0.13.0", + "group", "hkdf", "pem-rfc7468", - "pkcs8 0.10.2", + "pkcs8", "rand_core 0.6.4", - "sec1 0.7.3", + "sec1", "subtle", "zeroize", ] @@ -2814,7 +2774,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1e1dacd0d2082dfcf1351c4bdd566bbe89a2b263235a2b50058f1e130a47277" dependencies = [ "bit-set", - "regex-automata 0.4.14", + "regex-automata 0.4.15", "regex-syntax 0.8.11", ] @@ -2831,16 +2791,6 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" -[[package]] -name = "ff" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "ff" version = "0.13.1" @@ -2860,7 +2810,8 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "file_url" version = "0.3.1" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d8c8b9119e366c1b4103d3ca9b5e09cc5684ae14f1265d1472d0a7fbc61747" dependencies = [ "itertools 0.14.0", "percent-encoding", @@ -2910,9 +2861,9 @@ dependencies = [ [[package]] name = "flickzeug" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95ac51c7950d711fb128681fccb1dddd41c81eb230d78251e600a0296fdd30c" +checksum = "c80b84a6c2a0750383008cd384de902d69b4a9c5009f784e092259b98803bc45" dependencies = [ "nu-ansi-term 0.50.3", "strsim", @@ -2983,9 +2934,9 @@ dependencies = [ [[package]] name = "fs-err" -version = "3.3.0" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fde052dbfc920003cfd2c8e2c6e6d4cc7c1091538c3a24226cec0665ab08c0" +checksum = "b91aa448ca50d7e79433bdf3ee8d99215430d2ec02ade5aefab2a073a1822e8a" dependencies = [ "autocfg", "tokio", @@ -3111,11 +3062,11 @@ checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-timer" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" +checksum = "af43fadb8a98512d547e37b4e92e0ced13e205c061b87b4623eff01d918d6968" dependencies = [ - "gloo-timers 0.2.6", + "gloo-timers 0.4.0", "send_wrapper", ] @@ -3168,26 +3119,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if 1.0.4", - "js-sys", "libc", "r-efi 5.3.0", "wasip2", - "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if 1.0.4", "js-sys", "libc", "r-efi 6.0.0", "rand_core 0.10.1", - "wasip2", - "wasip3", "wasm-bindgen", ] @@ -3212,7 +3159,7 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.14", + "regex-automata 0.4.15", "regex-syntax 0.8.11", ] @@ -3222,7 +3169,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "ignore", "walkdir", ] @@ -3250,9 +3197,9 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" dependencies = [ "futures-channel", "futures-core", @@ -3262,9 +3209,9 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +checksum = "482ce8a491a501da4cd806bd190275363d674f2845005c6ddbd5d3e1dd54495d" dependencies = [ "futures-channel", "futures-core", @@ -3287,9 +3234,9 @@ dependencies = [ [[package]] name = "goblin" -version = "0.10.5" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "983a6aafb3b12d4c41ea78d39e189af4298ce747353945ff5105b54a056e5cd9" +checksum = "17582616a7718cca54cec18e534a76c7c4aec11a8b9a85695712f262fd15a4c8" dependencies = [ "log", "plain", @@ -3298,9 +3245,9 @@ dependencies = [ [[package]] name = "google-cloud-auth" -version = "1.10.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd4f8c914f230834828771125168eaa39bc6602e32cb0316ceeff2add10d449" +checksum = "a300d4011cb53573eafe2419630d303ced54aab6c194a6d9e4156de375800372" dependencies = [ "async-trait", "base64 0.22.1", @@ -3325,18 +3272,17 @@ dependencies = [ [[package]] name = "google-cloud-gax" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d597e9e4758fc778a60d8c28a8677629675ae40d8652ec000ae5f53f5ae7ec" +checksum = "4f60f45dd97ff91cedfcb6b2b9f860d3d84739386c3557027687c52cc0e698fd" dependencies = [ - "base64 0.22.1", "bytes", "futures", "google-cloud-rpc", "google-cloud-wkt", "http 1.4.2", "pin-project", - "rand 0.10.1", + "rand 0.10.2", "serde", "serde_json", "thiserror 2.0.18", @@ -3358,9 +3304,9 @@ dependencies = [ [[package]] name = "google-cloud-wkt" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5daa3084991800bcc5333d7e77bb19259a02b34ee35f35c27b49d602732306e" +checksum = "88e0186e2221bf82c5296500251b4650b111172c324984159a0de9f6bcaa18a5" dependencies = [ "base64 0.22.1", "bytes", @@ -3372,33 +3318,22 @@ dependencies = [ "url", ] -[[package]] -name = "group" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" -dependencies = [ - "ff 0.12.1", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "group" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "ff 0.13.1", + "ff", "rand_core 0.6.4", "subtle", ] [[package]] name = "h2" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" +checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" dependencies = [ "atomic-waker", "bytes", @@ -3538,12 +3473,9 @@ dependencies = [ [[package]] name = "html-escape" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" -dependencies = [ - "utf8-width", -] +checksum = "46c1ff2d1cbf39efe5af0900ced8a069b5e61557a17544eb0c4a50239937389e" [[package]] name = "http" @@ -3665,9 +3597,9 @@ dependencies = [ [[package]] name = "http-content-range" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66cdb727cec723cee65912a74a7f9f0c3ad0c6f9df4f03d05a5c7a15398bbad1" +checksum = "0298eab7a8b2346aa6e6b3502dfddf643735e45864cbe4ce9c73606cecb8b53f" [[package]] name = "http-serde" @@ -3708,15 +3640,15 @@ dependencies = [ [[package]] name = "humantime" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" +checksum = "15cdd26707701c53297e2fa6afb323d55fbc1d0810c3aec078ae3ef0424c3c15" [[package]] name = "hybrid-array" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" +checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c" dependencies = [ "typenum", ] @@ -3746,9 +3678,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.9.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" dependencies = [ "atomic-waker", "bytes", @@ -3773,7 +3705,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ "http 1.4.2", - "hyper 1.9.0", + "hyper 1.10.1", "hyper-util", "log", "rustls", @@ -3789,7 +3721,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.9.0", + "hyper 1.10.1", "hyper-util", "pin-project-lite", "tokio", @@ -3804,7 +3736,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.9.0", + "hyper 1.10.1", "hyper-util", "native-tls", "tokio", @@ -3824,17 +3756,17 @@ dependencies = [ "futures-util", "http 1.4.2", "http-body 1.0.1", - "hyper 1.9.0", + "hyper 1.10.1", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.4", "system-configuration", "tokio", "tower-service", "tracing", - "windows-registry", + "windows-registry 0.6.1", ] [[package]] @@ -3943,12 +3875,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "ident_case" version = "1.0.1" @@ -3978,15 +3904,15 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.26" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b915661dd01db3f05050265b2477bcc6527b3792388e2749b41623cc592be67d" +checksum = "2adf14691c72bcfc1058740436a35bdd3ae9c07d1a941ef00b749e9ea16aefa7" dependencies = [ "crossbeam-deque", "globset", "log", "memchr", - "regex-automata 0.4.14", + "regex-automata 0.4.15", "same-file", "walkdir", "winapi-util", @@ -4017,9 +3943,9 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.18.4" +version = "0.18.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" +checksum = "9433806cd6b4ec1aba79c021c7e4c58fb4c3b9977c085062e611ac929998fb0c" dependencies = [ "console", "portable-atomic", @@ -4176,9 +4102,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.29" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34f877a98676d2fb664698d74cc6a51ce6c484ce8c770f05d0108ec9090aeb46" +checksum = "961d16382652bfdd8c6f68b223b26a8c93e0d475c672f414411db31c6c5c900e" dependencies = [ "defmt", "jiff-static", @@ -4194,9 +4120,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.29" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0666b5ab5ecaca213fc2a85b8c0083d9004e84ee2d5f9a7e0017aaf50986f25f" +checksum = "d0879bd39df99c4c5e2c6615ccc026391a423dde10532c573e6086eb94a802cc" dependencies = [ "proc-macro2", "quote", @@ -4205,9 +4131,9 @@ dependencies = [ [[package]] name = "jiff-tzdb" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c900ef84826f1338a557697dc8fc601df9ca9af4ac137c7fb61d4c6f2dfd3076" +checksum = "142bd39932ad231f10513df9ab62661fead8719872150b7ad02a2df79f4e141e" [[package]] name = "jiff-tzdb-platform" @@ -4294,23 +4220,22 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.3", "libc", ] [[package]] name = "js-sys" -version = "0.3.98" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ "cfg-if 1.0.4", "futures-util", - "once_cell", "wasm-bindgen", ] @@ -4471,7 +4396,7 @@ checksum = "790bedefcec85321e007ff3af84b4e417540d5c87b3c9779b9e247d1bcc3dab8" dependencies = [ "base64 0.22.1", "http-body 1.0.1", - "hyper 1.9.0", + "hyper 1.10.1", "hyper-rustls", "hyper-util", "jsonrpsee-core", @@ -4524,24 +4449,6 @@ dependencies = [ "url", ] -[[package]] -name = "jsonwebtoken" -version = "10.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eba32bfb4ffdeaca3e34431072faf01745c9b26d25504aa7a6cf5684334fc4fc" -dependencies = [ - "aws-lc-rs", - "base64 0.22.1", - "getrandom 0.2.17", - "js-sys", - "pem", - "serde", - "serde_json", - "signature 2.2.0", - "simple_asn1", - "zeroize", -] - [[package]] name = "junction" version = "1.4.2" @@ -4612,12 +4519,6 @@ dependencies = [ "spin 0.9.8", ] -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - [[package]] name = "libbz2-rs-sys" version = "0.2.5" @@ -4658,18 +4559,18 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libmimalloc-sys" -version = "0.1.48" +version = "0.1.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2892ae4ea6fa2cb7acb0e236a6880d39523239cd9089de71d220910ccc806790" +checksum = "6a45a52f43e1c16f667ccfe4dd8c85b7f7c204fd5e3bf46c5b0db9a5c3c0b8e9" dependencies = [ "cc", ] [[package]] name = "libredox" -version = "0.1.16" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" dependencies = [ "libc", ] @@ -4721,9 +4622,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.29" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "lru" @@ -4742,9 +4643,9 @@ checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" [[package]] name = "lzma-rust2" -version = "0.16.4" +version = "0.16.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce716bf1a316f47a280fc76295f6495b5bea4752bca01c3b3885e101b1c23c02" +checksum = "ca93e534d1142d1d0dcca6d25fe302508a5dfb40b302802904577725ea0b695b" dependencies = [ "sha2 0.11.0", ] @@ -4819,18 +4720,18 @@ dependencies = [ [[package]] name = "mea" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6747f54621d156e1b47eb6b25f39a941b9fc347f98f67d25d8881ff99e8ed832" +checksum = "2640d335e7273dacdcf51044026139b2e269c3bb0dfc3f8cb3496b85e3f6a42c" dependencies = [ "slab", ] [[package]] name = "memchr" -version = "2.8.2" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "memmap2" @@ -4843,9 +4744,9 @@ dependencies = [ [[package]] name = "memmap2" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" dependencies = [ "libc", ] @@ -4934,9 +4835,9 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebca48a43116bc25f18a61360f1be98412f50cc218f5e52c823086b999a4a21a" +checksum = "2d4139bb28d14ad1facf21d5eb8825051b326e172d216b39f6d31df53cc97862" dependencies = [ "libmimalloc-sys", ] @@ -4987,9 +4888,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" dependencies = [ "libc", "wasi", @@ -5080,7 +4981,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg-if 1.0.4", "cfg_aliases", "libc", @@ -5092,7 +4993,7 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg-if 1.0.4", "cfg_aliases", "libc", @@ -5104,7 +5005,7 @@ version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg-if 1.0.4", "cfg_aliases", "libc", @@ -5182,9 +5083,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" dependencies = [ "num-integer", "num-traits", @@ -5232,11 +5133,10 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b" dependencies = [ - "autocfg", "num-integer", "num-traits", ] @@ -5316,7 +5216,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "dispatch2", "objc2", ] @@ -5333,7 +5233,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "objc2", ] @@ -5390,13 +5290,12 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "open" -version = "5.3.5" +version = "5.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fbaa89d2ddc8473c78a3adf69eea8cffa28c483b8e02a971ef31527cd0fc92c" +checksum = "cd8d3b65c44123a56e0133d2cd06ce4361bd3ca99d41198b2f25e3c3db9b8b4a" dependencies = [ "is-wsl", "libc", - "pathdiff", ] [[package]] @@ -5500,7 +5399,7 @@ dependencies = [ "itertools 0.10.5", "log", "oauth2", - "p256 0.13.2", + "p256", "p384", "rand 0.8.6", "rsa", @@ -5518,11 +5417,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.80" +version = "0.10.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967" +checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg-if 1.0.4", "foreign-types", "libc", @@ -5558,9 +5457,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.116" +version = "0.9.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4" +checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695" dependencies = [ "cc", "libc", @@ -5651,25 +5550,14 @@ version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" -[[package]] -name = "p256" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" -dependencies = [ - "ecdsa 0.14.8", - "elliptic-curve 0.12.3", - "sha2 0.10.9", -] - [[package]] name = "p256" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" dependencies = [ - "ecdsa 0.16.9", - "elliptic-curve 0.13.8", + "ecdsa", + "elliptic-curve", "primeorder", "sha2 0.10.9", ] @@ -5680,8 +5568,8 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" dependencies = [ - "ecdsa 0.16.9", - "elliptic-curve 0.13.8", + "ecdsa", + "elliptic-curve", "primeorder", "sha2 0.10.9", ] @@ -5758,7 +5646,8 @@ checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" [[package]] name = "path_resolver" version = "0.2.11" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a6d8be98ef9723e752c20eef948d3195d4e1314bc3cc033a8ff26b4e31d660" dependencies = [ "ahash", "fs-err", @@ -5847,9 +5736,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.6" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" +checksum = "47627dd7305c6a2d6c8c6bcd24c5a4c17dbbf425f4f9c5313e724b38fc9782e9" dependencies = [ "memchr", "ucd-trie", @@ -5857,9 +5746,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.8.6" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" +checksum = "4b4254325ecad416ab689e27ba51da03ba01a9632bc6e108f5fe7c3c4ad29d58" dependencies = [ "pest", "pest_generator", @@ -5867,9 +5756,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.6" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" +checksum = "6c4c0e91ead7a8f7acecbca6f003fc2e8282b1dbe2dd9c9d2f16aba42995e0a7" dependencies = [ "pest", "pest_meta", @@ -5880,12 +5769,11 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.8.6" +version = "2.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" +checksum = "f9744bc48116fee06334924bb5f2bad41eed5e89bd26e29b0b799f9a3f82c210" dependencies = [ "pest", - "sha2 0.10.9", ] [[package]] @@ -5934,7 +5822,7 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pixi" -version = "0.72.0" +version = "0.72.2" dependencies = [ "astral-reqwest-middleware", "async-trait", @@ -5994,7 +5882,7 @@ dependencies = [ [[package]] name = "pixi-build-cmake" -version = "0.4.3" +version = "0.4.4" dependencies = [ "async-trait", "fs-err", @@ -6020,7 +5908,7 @@ dependencies = [ [[package]] name = "pixi-build-mojo" -version = "0.2.3" +version = "0.2.4" dependencies = [ "async-trait", "fs-err", @@ -6043,7 +5931,7 @@ dependencies = [ [[package]] name = "pixi-build-python" -version = "0.8.2" +version = "0.8.3" dependencies = [ "async-trait", "fs-err", @@ -6073,7 +5961,7 @@ dependencies = [ [[package]] name = "pixi-build-r" -version = "0.1.4" +version = "0.1.5" dependencies = [ "async-trait", "fs-err", @@ -6097,7 +5985,7 @@ dependencies = [ [[package]] name = "pixi-build-rattler-build" -version = "0.4.3" +version = "0.4.4" dependencies = [ "async-trait", "fs-err", @@ -6121,9 +6009,10 @@ dependencies = [ [[package]] name = "pixi-build-ros" -version = "0.6.3" +version = "0.6.5" dependencies = [ "astral-reqwest-middleware", + "astral-reqwest-retry", "async-trait", "fs-err", "http-cache-reqwest", @@ -6132,6 +6021,7 @@ dependencies = [ "miette 7.6.0", "pathdiff", "pixi_build_backend", + "pixi_build_discovery", "pixi_build_types", "pixi_glob", "rattler_build_jinja", @@ -6140,6 +6030,7 @@ dependencies = [ "rattler_conda_types", "regex", "reqwest", + "retry-policies", "roxmltree", "serde", "serde_json", @@ -6153,7 +6044,7 @@ dependencies = [ [[package]] name = "pixi-build-rust" -version = "0.5.3" +version = "0.5.4" dependencies = [ "async-trait", "cargo_toml", @@ -7215,7 +7106,7 @@ dependencies = [ "rayon", "serde", "serde_json", - "shlex 2.0.1", + "shlex", "tempfile", "thiserror 2.0.18", "tokio", @@ -7278,7 +7169,7 @@ dependencies = [ "rattler_digest", "rattler_networking", "reqwest", - "sevenz-rust2 0.21.1", + "sevenz-rust2 0.21.3", "tar", "tempfile", "thiserror 2.0.18", @@ -7412,9 +7303,9 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ - "der 0.7.10", - "pkcs8 0.10.2", - "spki 0.7.3", + "der", + "pkcs8", + "spki", ] [[package]] @@ -7425,21 +7316,11 @@ checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" dependencies = [ "aes 0.8.4", "cbc 0.1.2", - "der 0.7.10", + "der", "pbkdf2", "scrypt", "sha2 0.10.9", - "spki 0.7.3", -] - -[[package]] -name = "pkcs8" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" -dependencies = [ - "der 0.6.1", - "spki 0.6.0", + "spki", ] [[package]] @@ -7448,10 +7329,10 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.10", + "der", "pkcs5", "rand_core 0.6.4", - "spki 0.7.3", + "spki", ] [[package]] @@ -7468,13 +7349,13 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "plist" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092791278e026273c1b65bbdcfbba3a300f2994c896bd01ab01da613c29c46f1" +checksum = "7da1d65da6dd5d1e44199ac0f58712d241c0f439f80adea8924d832384087f85" dependencies = [ "base64 0.22.1", "indexmap 2.14.0", - "quick-xml 0.39.4", + "quick-xml 0.41.0", "serde", "time", ] @@ -7536,23 +7417,13 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn", -] - [[package]] name = "primeorder" version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" dependencies = [ - "elliptic-curve 0.13.8", + "elliptic-curve", ] [[package]] @@ -7572,29 +7443,7 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.11+spec-1.1.0", -] - -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn", + "toml_edit 0.25.12+spec-1.1.0", ] [[package]] @@ -7612,7 +7461,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25485360a54d6861439d60facef26de713b1e126bf015ec8f98239467a2b82f7" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "flate2", "procfs-core", "rustix 1.1.4", @@ -7624,7 +7473,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6401bf7b6af22f78b563665d15a22e9aef27775b79b149a66ca022468a4e405" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "hex", ] @@ -7636,7 +7485,7 @@ checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.11.1", + "bitflags 2.13.0", "num-traits", "rand 0.9.4", "rand_chacha 0.9.0", @@ -7649,9 +7498,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" +checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1" dependencies = [ "bytes", "prost-derive", @@ -7659,9 +7508,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" dependencies = [ "anyhow", "itertools 0.14.0", @@ -7672,9 +7521,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" +checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a" dependencies = [ "prost", ] @@ -7794,11 +7643,30 @@ dependencies = [ "serde", ] +[[package]] +name = "quick-xml" +version = "0.40.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2474bd2e5029e7ccb6abb2ba48cf2383a333851dedf495901544281590c7da7f" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "quick-xml" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" +dependencies = [ + "memchr", +] + [[package]] name = "quinn" -version = "0.11.9" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" dependencies = [ "bytes", "cfg_aliases", @@ -7807,7 +7675,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.5.10", + "socket2 0.6.4", "thiserror 2.0.18", "tokio", "tracing", @@ -7816,15 +7684,16 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.14" +version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" dependencies = [ "aws-lc-rs", "bytes", - "getrandom 0.3.4", + "getrandom 0.4.3", "lru-slab", - "rand 0.9.4", + "rand 0.10.2", + "rand_pcg", "ring", "rustc-hash", "rustls", @@ -7838,23 +7707,23 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.4", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "quote" -version = "1.0.45" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] @@ -7885,9 +7754,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rancor" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a063ea72381527c2a0561da9c80000ef822bdd7c3241b1cc1b12100e3df081ee" +checksum = "daff8b7b3ccf5f7ba270b3e7a0a4d4c701c5797e38dec27c7e2c3dbb830fed1c" dependencies = [ "ptr_meta", ] @@ -7915,12 +7784,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ "chacha20", - "getrandom 0.4.2", + "getrandom 0.4.3", "rand_core 0.10.1", ] @@ -7968,6 +7837,15 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" +[[package]] +name = "rand_pcg" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" +dependencies = [ + "rand_core 0.10.1", +] + [[package]] name = "rand_xorshift" version = "0.4.0" @@ -7979,8 +7857,9 @@ dependencies = [ [[package]] name = "rattler" -version = "0.46.0" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e3120ba76d85c4750f21d2ee72245a358eed7a66c076f3a67c72383595e46ba" dependencies = [ "anyhow", "astral-reqwest-middleware", @@ -7999,7 +7878,7 @@ dependencies = [ "itertools 0.14.0", "jiff", "memchr", - "memmap2 0.9.10", + "memmap2 0.9.11", "oauth2-reqwest", "once_cell", "open", @@ -8032,8 +7911,7 @@ dependencies = [ [[package]] name = "rattler_build_core" version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "062894c59d2fb709f6567de7114d5e82e618a18f98bbb6985ba8fed3b1cafc03" +source = "git+https://github.com/prefix-dev/rattler-build?branch=main#1e69a762a08963bd4979b31c820b864229de115f" dependencies = [ "anyhow", "arwen-codesign", @@ -8059,7 +7937,7 @@ dependencies = [ "jiff", "line-ending", "memchr", - "memmap2 0.9.10", + "memmap2 0.9.11", "miette 7.6.0", "minijinja", "num_cpus", @@ -8117,8 +7995,7 @@ dependencies = [ [[package]] name = "rattler_build_jinja" version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaa42628f0be2d3a391cea39f59c86fec6518e8e695406fff692ab7b89f1a5f3" +source = "git+https://github.com/prefix-dev/rattler-build?branch=main#1e69a762a08963bd4979b31c820b864229de115f" dependencies = [ "fs-err", "indexmap 2.14.0", @@ -8139,8 +8016,7 @@ dependencies = [ [[package]] name = "rattler_build_networking" version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce268d916e05ec5c80a5683a8c1358e46f7406a3a8d489788ad3497be692e656" +source = "git+https://github.com/prefix-dev/rattler-build?branch=main#1e69a762a08963bd4979b31c820b864229de115f" dependencies = [ "astral-reqwest-middleware", "astral-reqwest-retry", @@ -8152,8 +8028,7 @@ dependencies = [ [[package]] name = "rattler_build_recipe" version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc70da8f49df547e6473551efc845f85cfa3e1298fa21b4589c0064d84e73292" +source = "git+https://github.com/prefix-dev/rattler-build?branch=main#1e69a762a08963bd4979b31c820b864229de115f" dependencies = [ "fs-err", "globset", @@ -8187,8 +8062,7 @@ dependencies = [ [[package]] name = "rattler_build_script" version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b423552711a5bf944104632f4d7828f296bd9032e2e052623a922edef7b98ccf" +source = "git+https://github.com/prefix-dev/rattler-build?branch=main#1e69a762a08963bd4979b31c820b864229de115f" dependencies = [ "clap", "console", @@ -8211,8 +8085,7 @@ dependencies = [ [[package]] name = "rattler_build_source_cache" version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f915ad0658f40afa210892b3261f75dc9668512f73192d1b623e0929d8a769" +source = "git+https://github.com/prefix-dev/rattler-build?branch=main#1e69a762a08963bd4979b31c820b864229de115f" dependencies = [ "astral-reqwest-middleware", "astral-reqwest-retry", @@ -8250,8 +8123,7 @@ dependencies = [ [[package]] name = "rattler_build_types" version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfbb59c6d12f7fea99f98191967436c9917e69633bf86e4e38e473164738132b" +source = "git+https://github.com/prefix-dev/rattler-build?branch=main#1e69a762a08963bd4979b31c820b864229de115f" dependencies = [ "globset", "itertools 0.14.0", @@ -8266,8 +8138,7 @@ dependencies = [ [[package]] name = "rattler_build_variant_config" version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c386043b804f78eacc429524d75146d3564c89a49d8e1cfe58e70538e0e529bf" +source = "git+https://github.com/prefix-dev/rattler-build?branch=main#1e69a762a08963bd4979b31c820b864229de115f" dependencies = [ "fs-err", "marked-yaml", @@ -8287,8 +8158,7 @@ dependencies = [ [[package]] name = "rattler_build_yaml_parser" version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f5a5ceda725bab5b6f2b19d3c657f878deb072ca081d2cd44797c38177d0b4" +source = "git+https://github.com/prefix-dev/rattler-build?branch=main#1e69a762a08963bd4979b31c820b864229de115f" dependencies = [ "marked-yaml", "miette 7.6.0", @@ -8299,8 +8169,9 @@ dependencies = [ [[package]] name = "rattler_cache" -version = "0.10.1" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2be7994388cfd959c35e7e31eeb0a206b0b389f426511f08d004bf7ba103897" dependencies = [ "ahash", "anyhow", @@ -8332,8 +8203,9 @@ dependencies = [ [[package]] name = "rattler_conda_types" -version = "0.47.2" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "017a8ae50486c176ed5dcd2b2118883e1eb89abcacb6fdb434b6f5cb5aa2fdf7" dependencies = [ "ahash", "core-foundation 0.10.1", @@ -8347,7 +8219,7 @@ dependencies = [ "itertools 0.14.0", "jiff", "lazy-regex", - "memmap2 0.9.10", + "memmap2 0.9.11", "nom 8.0.0", "nom-language", "purl", @@ -8374,8 +8246,9 @@ dependencies = [ [[package]] name = "rattler_config" -version = "0.5.2" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59903c0728da7418179f5d5e5516339ea279acee06247319dc6da234f6c43dd7" dependencies = [ "dirs", "fs-err", @@ -8393,7 +8266,8 @@ dependencies = [ [[package]] name = "rattler_digest" version = "1.3.1" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e4af3c4e8b0cf496e66a5f2e7244364409a20cd4338ad9b331bd7247de32b69" dependencies = [ "blake2 0.11.0-rc.6", "digest 0.11.3", @@ -8432,8 +8306,9 @@ dependencies = [ [[package]] name = "rattler_index" -version = "0.30.7" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +version = "0.30.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11cc76cfe51931dcbade151e2e2643fd465b41e259248c1beb9cc97ee8417b74" dependencies = [ "ahash", "anyhow", @@ -8471,8 +8346,9 @@ dependencies = [ [[package]] name = "rattler_lock" -version = "0.31.3" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +version = "0.31.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc13501d19e0994f1d460569a89b595d3a7808d9c7948ec44f29b3cb202bc9b" dependencies = [ "ahash", "file_url", @@ -8500,7 +8376,8 @@ dependencies = [ [[package]] name = "rattler_macros" version = "1.1.1" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3d93067b745b200dd741e872f4160de24d1b972ee63db65e8a2cf6a447f1ff" dependencies = [ "quote", "syn", @@ -8508,8 +8385,9 @@ dependencies = [ [[package]] name = "rattler_menuinst" -version = "0.2.68" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +version = "0.2.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b832bfe293a9f7912e9ecb5fefdfaf0e5858420a238b8efe10533982a3b7bb75" dependencies = [ "configparser", "dirs", @@ -8526,20 +8404,21 @@ dependencies = [ "serde", "serde_json", "sha2 0.11.0", - "shlex 2.0.1", + "shlex", "tempfile", "thiserror 2.0.18", "tracing", "unicode-normalization", "which", "windows 0.61.3", - "windows-registry", + "windows-registry 0.5.3", ] [[package]] name = "rattler_networking" -version = "0.30.0" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a976a1ab13c2a706bd09ae5376358b2cc062d815a06089a8127ce59fbdce0c9" dependencies = [ "ambient-id", "anyhow", @@ -8555,7 +8434,7 @@ dependencies = [ "dirs", "fs-err", "futures", - "getrandom 0.4.2", + "getrandom 0.4.3", "google-cloud-auth", "http 1.4.2", "http-auth", @@ -8563,6 +8442,7 @@ dependencies = [ "keyring-core", "netrc-rs", "rattler_config", + "regex", "reqwest", "retry-policies", "serde", @@ -8577,8 +8457,9 @@ dependencies = [ [[package]] name = "rattler_package_streaming" -version = "0.26.6" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +version = "0.26.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66c4eab28b2bb0132d281612f23192d2335356b20ea538fa40dfd0dd5ddc7c65" dependencies = [ "astral-reqwest-middleware", "astral-tokio-tar", @@ -8592,7 +8473,7 @@ dependencies = [ "futures", "futures-util", "getrandom 0.2.17", - "getrandom 0.4.2", + "getrandom 0.4.3", "hex", "http 1.4.2", "jiff", @@ -8632,7 +8513,8 @@ dependencies = [ [[package]] name = "rattler_pty" version = "0.2.14" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19145200e8c578be6dca325fbacf375a57f86d4a7ccf85d2d8ee193ddfb10dd" dependencies = [ "libc", "nix 0.30.1", @@ -8643,7 +8525,8 @@ dependencies = [ [[package]] name = "rattler_redaction" version = "0.2.1" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d1893dff3da09d778304797291869b17287e35a785cd8bc58fb9cd4760ef51b" dependencies = [ "astral-reqwest-middleware", "reqwest", @@ -8652,8 +8535,9 @@ dependencies = [ [[package]] name = "rattler_repodata_gateway" -version = "0.29.7" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5660f0974ffeef30389d01b5b8a390ca064dad75999d625305a8b07db3d21cbb" dependencies = [ "ahash", "anyhow", @@ -8682,7 +8566,7 @@ dependencies = [ "jiff", "json-patch", "libc", - "memmap2 0.9.10", + "memmap2 0.9.11", "parking_lot 0.12.5", "pin-project-lite", "rattler_cache", @@ -8714,8 +8598,9 @@ dependencies = [ [[package]] name = "rattler_s3" -version = "0.2.6" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaf41b431123d3c1a79c6802152d23fb896213691e058a1d636d822c9613af2f" dependencies = [ "aws-config", "aws-credential-types", @@ -8730,8 +8615,9 @@ dependencies = [ [[package]] name = "rattler_shell" -version = "0.27.8" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c10583e7532955b7cd4579ddd457e91b648bf4a1232c4192384c61a08b8ff03c" dependencies = [ "anyhow", "enum_dispatch", @@ -8741,7 +8627,7 @@ dependencies = [ "rattler_conda_types", "rattler_pty", "serde_json", - "shlex 2.0.1", + "shlex", "sysinfo", "tempfile", "thiserror 2.0.18", @@ -8751,8 +8637,9 @@ dependencies = [ [[package]] name = "rattler_solve" -version = "7.2.0" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +version = "7.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5972bed20c404d943da0ed351bbd97cd91b01086620bc68563e9dfe173c198" dependencies = [ "futures", "hex", @@ -8769,8 +8656,9 @@ dependencies = [ [[package]] name = "rattler_upload" -version = "0.8.2" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0aec8ed35b75444dca1fbea81b51d5fb437552918e4bd5c85cbb98c05ca5a11" dependencies = [ "astral-reqwest-middleware", "astral-reqwest-retry", @@ -8807,8 +8695,9 @@ dependencies = [ [[package]] name = "rattler_virtual_packages" -version = "3.0.2" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ff8fc437511c1ade556cc9753c99f64d4d6097fa82e6ab3008ca935abd8a48" dependencies = [ "archspec", "libloading", @@ -8858,7 +8747,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -8894,9 +8783,9 @@ dependencies = [ [[package]] name = "reflink-copy" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13362233b147e57674c37b802d216b7c5e3dcccbed8967c84f0d8d223868ae27" +checksum = "d9dd7ab4af0363d5ccfd2838d782a28196cf32a5cc2e4fe3c5dc83f2be588b8b" dependencies = [ "cfg-if 1.0.4", "libc", @@ -8906,13 +8795,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.4" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" +checksum = "2a0e75113e14dc5acb068cd0786884f214f1312650a3d36d269f5c4f3cdee8a2" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.14", + "regex-automata 0.4.15", "regex-syntax 0.8.11", ] @@ -8927,9 +8816,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +checksum = "1f388202e4b80542a0921078cc23b6333bcf1409c1e3f86404cae4766a6131db" dependencies = [ "aho-corasick", "memchr", @@ -8962,18 +8851,18 @@ checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "rend" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cadadef317c2f20755a64d7fdc48f9e7178ee6b0e1f7fce33fa60f1d68a276e6" +checksum = "663ba70707f96e871406fe10d68128412e619b06d1d47cb91c3a4c6501176240" dependencies = [ "bytecheck", ] [[package]] name = "reqsign" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f343280e2e5ce07f97f32ead07a68824cb9cea60093ad78f22664011f90ae47" +checksum = "124e8be679553a5d8c52faa4e5169a8f6727ea8c8e4ecb20902a45d25e3b40ae" dependencies = [ "reqsign-aws-v4", "reqsign-azure-storage", @@ -8986,37 +8875,37 @@ dependencies = [ [[package]] name = "reqsign-aws-v4" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44eaca382e94505a49f1a4849658d153aebf79d9c1a58e5dd3b10361511e9f43" +checksum = "7b75624bd8a466e37ddc0a7b6c33ac859a85347c153a916e1dd9d0b68338f74a" dependencies = [ "anyhow", "bytes", "form_urlencoded", + "hex", "http 1.4.2", "log", "percent-encoding", - "quick-xml 0.39.4", + "quick-xml 0.40.1", "reqsign-core", "rust-ini", "serde", "serde_json", "serde_urlencoded", - "sha1 0.10.6", + "sha1 0.11.0", ] [[package]] name = "reqsign-azure-storage" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a321980405d596bd34aaf95c4722a3de4128a67fd19e74a81a83aa3fdf082e6" +checksum = "62b96928e73ad984de1d99e382749d09e5dab7dd707b767974f7e40aa926b82f" dependencies = [ "anyhow", "base64 0.22.1", "bytes", "form_urlencoded", "http 1.4.2", - "jsonwebtoken", "log", "pem", "percent-encoding", @@ -9024,14 +8913,14 @@ dependencies = [ "rsa", "serde", "serde_json", - "sha1 0.10.6", + "sha1 0.11.0", ] [[package]] name = "reqsign-command-execute-tokio" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4e0330fd26f72c7c6c4f09ab23fdf424b2a669ffdacc562803b2b3eecc7198" +checksum = "13460892332fd1ae7bc344ca063379beae3f0db50e7066af72467c938c3eea9f" dependencies = [ "reqsign-core", "tokio", @@ -9039,9 +8928,9 @@ dependencies = [ [[package]] name = "reqsign-core" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b10302cf0a7d7e7352ba211fc92c3c5bebf1286153e49cc5aa87348078a8e102" +checksum = "a5fa5cb48808693614d1701fcd3db0b30fa292e0f18e122ae068b6d32eaeed3f" dependencies = [ "anyhow", "base64 0.22.1", @@ -9049,21 +8938,24 @@ dependencies = [ "form_urlencoded", "futures", "hex", - "hmac 0.12.1", + "hmac 0.13.0", "http 1.4.2", "jiff", "log", "percent-encoding", - "sha1 0.10.6", - "sha2 0.10.9", + "rsa", + "serde", + "serde_json", + "sha1 0.11.0", + "sha2 0.11.0", "windows-sys 0.61.2", ] [[package]] name = "reqsign-file-read-tokio" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d89295b3d17abea31851cc8de55d843d89c52132c864963c38d41920613dc5" +checksum = "6a4b6f3a3fd29ffcc99a90aec585a65217783badfd73acddf847b63ae683bda9" dependencies = [ "anyhow", "reqsign-core", @@ -9072,13 +8964,12 @@ dependencies = [ [[package]] name = "reqsign-google" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35cc609b49c69e76ecaceb775a03f792d1ed3e7755ab3548d4534fd801e3242e" +checksum = "eb215d0876a18b6bd9cdd380b589e5292aaa638ca15266de794b1122d898b6b2" dependencies = [ "form_urlencoded", "http 1.4.2", - "jsonwebtoken", "log", "percent-encoding", "reqsign-aws-v4", @@ -9086,15 +8977,14 @@ dependencies = [ "rsa", "serde", "serde_json", - "sha2 0.10.9", "tokio", ] [[package]] name = "reqsign-http-send-reqwest" -version = "4.0.0" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46db7dfc9632310d2bdc7978c2e217187cd814842da66b3daf20a45f4e8a1e5e" +checksum = "6089b23d9ba77aa6a8e5cf38d11550da23458d1c455645ae59e52294ffe7d26f" dependencies = [ "anyhow", "bytes", @@ -9122,7 +9012,7 @@ dependencies = [ "http 1.4.2", "http-body 1.0.1", "http-body-util", - "hyper 1.9.0", + "hyper 1.10.1", "hyper-rustls", "hyper-tls", "hyper-util", @@ -9185,18 +9075,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc05fbf560421a0357a750cbe78c7ca19d4923918490daabba313d5dbc871e47" dependencies = [ - "rand 0.10.1", -] - -[[package]] -name = "rfc6979" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" -dependencies = [ - "crypto-bigint 0.4.9", - "hmac 0.12.1", - "zeroize", + "rand 0.10.2", ] [[package]] @@ -9225,9 +9104,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.8.16" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73389e0c99e664f919275ab5b5b0471391fe9a8de61e1dff9b1eaf56a90f16e3" +checksum = "815cc8a37159a463064825246cadb07961e25cd9885908606f6d08a98d8f8874" dependencies = [ "bytecheck", "bytes", @@ -9245,9 +9124,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.8.16" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d2ed0b54125315fb36bd021e82d314d1c126548f871634b483f46b31d13cac6" +checksum = "c0ed1a78a1b19d184b0daa629dd9a024573173ec7d485b287cb369fb3607cc1c" dependencies = [ "proc-macro2", "quote", @@ -9303,11 +9182,11 @@ dependencies = [ "num-integer", "num-traits", "pkcs1", - "pkcs8 0.10.2", + "pkcs8", "rand_core 0.6.4", "sha2 0.10.9", - "signature 2.2.0", - "spki 0.7.3", + "signature", + "spki", "subtle", "zeroize", ] @@ -9353,15 +9232,15 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" +checksum = "b74b56ffa8bb2830709a538c2cbcae9aa062db0d2a42563bfb09bdaae44020eb" [[package]] name = "rustc-hash" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" [[package]] name = "rustc_version" @@ -9387,7 +9266,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -9400,7 +9279,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.12.1", @@ -9409,9 +9288,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.40" +version = "0.23.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" +checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" dependencies = [ "aws-lc-rs", "log", @@ -9437,9 +9316,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046" dependencies = [ "web-time", "zeroize", @@ -9507,9 +9386,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "rusty-fork" @@ -9643,30 +9522,16 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" -[[package]] -name = "sec1" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" -dependencies = [ - "base16ct 0.1.1", - "der 0.6.1", - "generic-array", - "pkcs8 0.9.0", - "subtle", - "zeroize", -] - [[package]] name = "sec1" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ - "base16ct 0.2.0", - "der 0.7.10", + "base16ct", + "der", "generic-array", - "pkcs8 0.10.2", + "pkcs8", "subtle", "zeroize", ] @@ -9705,7 +9570,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -9747,9 +9612,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "send_wrapper" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" @@ -9966,7 +9831,7 @@ dependencies = [ "bzip2 0.6.1", "cbc 0.1.2", "crc32fast", - "getrandom 0.4.2", + "getrandom 0.4.3", "js-sys", "lzma-rust2", "ppmd-rust", @@ -9976,15 +9841,15 @@ dependencies = [ [[package]] name = "sevenz-rust2" -version = "0.21.1" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081a399c6762c4a9bda9233f502aca74b6ca6a0caaff4d218b12887eac4b6adc" +checksum = "0b5d71c87d24cb22976f3f6e6c2c9296ef1f6958394e2b868d56ca01b082798a" dependencies = [ - "aes 0.9.0", + "aes 0.9.1", "bzip2 0.6.1", - "cbc 0.2.0", + "cbc 0.2.1", "crc32fast", - "getrandom 0.4.2", + "getrandom 0.4.3", "js-sys", "lzma-rust2", "ppmd-rust", @@ -10079,12 +9944,6 @@ dependencies = [ "os_str_bytes", ] -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - [[package]] name = "shlex" version = "2.0.1" @@ -10111,16 +9970,6 @@ dependencies = [ "libc", ] -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - [[package]] name = "signature" version = "2.2.0" @@ -10157,14 +10006,14 @@ dependencies = [ "aws-lc-rs", "base64 0.22.1", "const-oid 0.9.6", - "der 0.7.10", + "der", "digest 0.10.7", "pem", "rand_core 0.9.5", "sha2 0.10.9", - "signature 2.2.0", + "signature", "sigstore-types", - "spki 0.7.3", + "spki", "thiserror 2.0.18", "tracing", "x509-cert", @@ -10290,7 +10139,7 @@ dependencies = [ "cmpv2", "cms", "const-oid 0.9.6", - "der 0.7.10", + "der", "hex", "jiff", "rand 0.9.4", @@ -10379,9 +10228,9 @@ checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "simd-json" -version = "0.17.0" +version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4255126f310d2ba20048db6321c81ab376f6a6735608bf11f0785c41f01f64e3" +checksum = "e32d7ab2678282d21e53374fbead7119b7eacbede73685dcaac472870a29a11c" dependencies = [ "halfbrown", "ref-cast", @@ -10415,9 +10264,9 @@ checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" [[package]] name = "similar" -version = "3.1.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04d93e861ede2e497b47833469b8ec9d5c07fa4c78ce7a00f6eb7dd8168b4b3f" +checksum = "e6505efef05804732ed8a3f2d4f279429eb485bd69d5b0cc6b19cc02005cda16" dependencies = [ "bstr", "unicode-segmentation", @@ -10430,25 +10279,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "997e6ca38e97437973fc9f7f50a50d1274cacd874341a4960fea90067291038c" dependencies = [ "console", - "similar 3.1.0", -] - -[[package]] -name = "simple_asn1" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" -dependencies = [ - "num-bigint", - "num-traits", - "thiserror 2.0.18", - "time", + "similar 3.1.1", ] [[package]] name = "simple_spawn_blocking" version = "1.1.0" -source = "git+https://github.com/conda/rattler?branch=claude%2Frattler-shared-config-design-m8d2gb#5ded1a968fa22cf4329ec95f9b31d82f0db26598" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55c0b0b683828aa9d4f5c0e59b0c856a12c30a65b5f1ca4292664734d76fa9c2" dependencies = [ "tokio", ] @@ -10470,18 +10308,18 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.15.1" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" dependencies = [ "serde", ] [[package]] name = "smawk" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" +checksum = "e8e2fb0f499abb4d162f2bedad68f5ef91a1682b5a03596ddb67efd37768d100" [[package]] name = "socket2" @@ -10495,9 +10333,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", "windows-sys 0.61.2", @@ -10548,16 +10386,6 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" -[[package]] -name = "spki" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" -dependencies = [ - "base64ct", - "der 0.6.1", -] - [[package]] name = "spki" version = "0.7.3" @@ -10565,7 +10393,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der 0.7.10", + "der", ] [[package]] @@ -10668,9 +10496,9 @@ checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" [[package]] name = "syn" -version = "2.0.117" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -10726,7 +10554,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7dddc5f0fee506baf8b9fdb989e242f17e4b11c61dfbb0635b705217199eea" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "byteorder", "enum-as-inner", "libc", @@ -10736,9 +10564,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.39.3" +version = "0.39.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21d0d938c10fcda3e897e28aaddf4ab462375d411f4378cd63b1c945f69aba96" +checksum = "d2071df9448915b71c4fe6d25deaf1c22f12bd234f01540b77312bb8e41361e6" dependencies = [ "libc", "memchr", @@ -10755,7 +10583,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -10819,7 +10647,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.2", + "getrandom 0.4.3", "once_cell", "rustix 1.1.4", "windows-sys 0.61.2", @@ -10934,12 +10762,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.47" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50" dependencies = [ "deranged", - "itoa", "js-sys", "num-conv", "powerfmt", @@ -10950,15 +10777,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "time-macros" -version = "0.2.27" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f" dependencies = [ "num-conv", "time-core", @@ -11031,7 +10858,7 @@ dependencies = [ "parking_lot 0.12.5", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.3", + "socket2 0.6.4", "tokio-macros", "tracing", "windows-sys 0.61.2", @@ -11195,9 +11022,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.11+spec-1.1.0" +version = "0.25.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" dependencies = [ "indexmap 2.14.0", "serde_core", @@ -11237,12 +11064,12 @@ dependencies = [ "http 1.4.2", "http-body 1.0.1", "http-body-util", - "hyper 1.9.0", + "hyper 1.10.1", "hyper-timeout", "hyper-util", "percent-encoding", "pin-project", - "socket2 0.6.3", + "socket2 0.6.4", "sync_wrapper", "tokio", "tokio-stream", @@ -11289,7 +11116,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ "async-compression", - "bitflags 2.11.1", + "bitflags 2.13.0", "bytes", "futures-core", "futures-util", @@ -11439,9 +11266,9 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "typenum" -version = "1.20.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "ucd-trie" @@ -11495,9 +11322,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.13.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-width" @@ -11566,12 +11393,6 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" -[[package]] -name = "utf8-width" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1292c0d970b54115d14f2492fe0170adf21d68a1de108eebc51c1df4f346a091" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -11586,13 +11407,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.1" +version = "1.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53" dependencies = [ - "getrandom 0.4.2", + "getrandom 0.4.3", "js-sys", - "rand 0.10.1", + "rand 0.10.2", "serde_core", "wasm-bindgen", ] @@ -11698,7 +11519,7 @@ dependencies = [ "tempfile", "thiserror 2.0.18", "tokio", - "toml_edit 0.25.11+spec-1.1.0", + "toml_edit 0.25.12+spec-1.1.0", "tracing", "uv-auth", "uv-cache-key", @@ -11992,7 +11813,7 @@ source = "git+https://github.com/astral-sh/uv?tag=0.11.15#3cffe97c2e48c9e49422c7 dependencies = [ "arcstr", "astral-version-ranges", - "bitflags 2.11.1", + "bitflags 2.13.0", "fs-err", "http 1.4.2", "itertools 0.14.0", @@ -12070,7 +11891,7 @@ name = "uv-flags" version = "0.0.48" source = "git+https://github.com/astral-sh/uv?tag=0.11.15#3cffe97c2e48c9e49422c738da3af95919dd0bf5" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -12155,7 +11976,7 @@ dependencies = [ "globset", "owo-colors", "regex", - "regex-automata 0.4.14", + "regex-automata 0.4.15", "thiserror 2.0.18", "tracing", "walkdir", @@ -12384,7 +12205,7 @@ name = "uv-platform-tags" version = "0.0.48" source = "git+https://github.com/astral-sh/uv?tag=0.11.15#3cffe97c2e48c9e49422c738da3af95919dd0bf5" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "memchr", "rkyv", "rustc-hash", @@ -12422,7 +12243,7 @@ dependencies = [ "serde", "serde-untagged", "thiserror 2.0.18", - "toml_edit 0.25.11+spec-1.1.0", + "toml_edit 0.25.12+spec-1.1.0", "tracing", "url", "uv-cache-key", @@ -12490,7 +12311,7 @@ dependencies = [ "uv-warnings", "which", "windows 0.61.3", - "windows-registry", + "windows-registry 0.5.3", ] [[package]] @@ -12597,7 +12418,7 @@ dependencies = [ "tokio", "tokio-stream", "toml 1.1.2+spec-1.1.0", - "toml_edit 0.25.11+spec-1.1.0", + "toml_edit 0.25.12+spec-1.1.0", "tracing", "url", "uv-cache-key", @@ -12707,7 +12528,7 @@ dependencies = [ "uv-fs", "uv-static", "windows 0.61.3", - "windows-registry", + "windows-registry 0.5.3", ] [[package]] @@ -12871,7 +12692,7 @@ dependencies = [ "thiserror 2.0.18", "tokio", "toml 1.1.2+spec-1.1.0", - "toml_edit 0.25.11+spec-1.1.0", + "toml_edit 0.25.12+spec-1.1.0", "tracing", "uv-build-backend", "uv-cache-key", @@ -12898,9 +12719,9 @@ checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "value-trait" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e80f0c733af0720a501b3905d22e2f97662d8eacfe082a75ed7ffb5ab08cb59" +checksum = "f3f4b4a98dfe54bc9ed3641af7ffcb837240269627dbd5cb047d13daa39736cc" dependencies = [ "float-cmp", "halfbrown", @@ -13001,27 +12822,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen 0.57.1", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" dependencies = [ - "wit-bindgen 0.51.0", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.121" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if 1.0.4", "once_cell", @@ -13032,9 +12844,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.71" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ "js-sys", "wasm-bindgen", @@ -13042,9 +12854,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.121" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -13052,9 +12864,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.121" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", @@ -13065,35 +12877,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.121" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap 2.14.0", - "wasm-encoder", - "wasmparser", -] - [[package]] name = "wasm-streams" version = "0.5.0" @@ -13107,18 +12897,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags 2.11.1", - "hashbrown 0.15.5", - "indexmap 2.14.0", - "semver", -] - [[package]] name = "wasmtimer" version = "0.4.3" @@ -13135,9 +12913,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.98" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b572dff8bcf38bad0fa19729c89bb5748b2b9b1d8be70cf90df697e3a8f32aa" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -13390,6 +13168,17 @@ dependencies = [ "windows-strings 0.4.2", ] +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + [[package]] name = "windows-result" version = "0.3.4" @@ -13694,100 +13483,12 @@ dependencies = [ "windows 0.48.0", ] -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap 2.14.0", - "prettyplease", - "syn", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.11.1", - "indexmap 2.14.0", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap 2.14.0", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - [[package]] name = "writeable" version = "0.6.3" @@ -13810,10 +13511,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94" dependencies = [ "const-oid 0.9.6", - "der 0.7.10", + "der", "sha1 0.10.6", - "signature 2.2.0", - "spki 0.7.3", + "signature", + "spki", "tls_codec", ] @@ -13842,7 +13543,7 @@ checksum = "f5ceece934a21607055b7ac5c25adb56a2ff559804b10705dc674d1d838c15e1" dependencies = [ "cmpv2", "cms", - "der 0.7.10", + "der", ] [[package]] @@ -13881,9 +13582,9 @@ dependencies = [ [[package]] name = "xxhash-rust" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" +checksum = "4d93c89cdc2d3a63c3ec48ffe926931bdc069eafa8e4402fe6d8f790c9d1e576" [[package]] name = "xz2" @@ -13916,9 +13617,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -13939,9 +13640,9 @@ dependencies = [ [[package]] name = "zbus" -version = "5.15.0" +version = "5.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3bcbf15c8708d7fc1be0c993622e0a5cbd5e8b52bfa40afa4c3e0cd8d724ac1" +checksum = "a28b97f866896a4be7aefd2b5a8e01bb6773d19a775d54ab28b4d094b9a4480e" dependencies = [ "async-broadcast", "async-recursion", @@ -13969,9 +13670,9 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "5.15.0" +version = "5.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51fa5406ad9175a8c825a931f8cf347116b531b3634fcb0b627c290f1f2516ff" +checksum = "5e05ad887425eecf5e8384dc2406a4a9313eb73468712fc1cdea362eb4fe0469" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -13984,9 +13685,9 @@ dependencies = [ [[package]] name = "zbus_names" -version = "4.3.2" +version = "4.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7074f3e50b894eac91750142016d30d0a89be8e67dbfd9704fb875825760e52d" +checksum = "1039ca249fee9559680f3a9f05b55e0761fee51af4f6c1e7d8c1f31e549721d2" dependencies = [ "serde", "winnow 1.0.3", @@ -13995,18 +13696,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.48" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.48" +version = "0.8.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" dependencies = [ "proc-macro2", "quote", @@ -14036,18 +13737,18 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" dependencies = [ "proc-macro2", "quote", @@ -14104,9 +13805,9 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.6.3" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be3d40e40a133f9c916ee3f9f4fa2d9d63435b5fbe1bfc6d9dae0aa0ada1513" +checksum = "b142a20ec14a91d5bc708c1dc21b080c550113d8aa77afa29635673a65dd02c5" [[package]] name = "zmij" @@ -14156,9 +13857,9 @@ dependencies = [ [[package]] name = "zvariant" -version = "5.11.0" +version = "5.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c1567a6ec68df868cbbfde844cfc6d81649fe5109a62b116b19fabd53e618ee" +checksum = "7cf057bb00bf5c9ad77abb6147b0ca4818236a1858416e9d988e40d6322fefa7" dependencies = [ "endi", "enumflags2", @@ -14170,9 +13871,9 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "5.11.0" +version = "5.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d5b780599bbde114e39d9a0799577fad1ced5105d38515745f7b3099d8ceda" +checksum = "8118ca6bda77bfc0ab51d660db0c955f2505eef854c9a449435bccb616933b31" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -14183,9 +13884,9 @@ dependencies = [ [[package]] name = "zvariant_utils" -version = "3.3.1" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d464f5733ffa07a3164d656f18533caace9d0638596721355d73256a410d691" +checksum = "90cb9383f9b45290407a1258b202d3f8f01db719eb60b4e4055c6375af4fc7c7" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 20dcd3a130..e7f213c559 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -229,12 +229,12 @@ zstd = { version = "0.13.3", default-features = false } # Rattler crates file_url = "0.3.0" -rattler = { version = "0.46", default-features = false } +rattler = { version = "0.47", default-features = false } rattler_cache = { version = "0.10", default-features = false } -rattler_conda_types = { version = "0.47", default-features = false, features = [ +rattler_conda_types = { version = "0.48", default-features = false, features = [ "rayon", ] } -rattler_config = { version = "0.5", default-features = false } +rattler_config = { version = "0.6", default-features = false } rattler_digest = { version = "1.3", default-features = false } rattler_index = { version = "0.30", default-features = false, features = [ "s3", @@ -246,7 +246,7 @@ rattler_networking = { version = "0.30", default-features = false, features = [ "google-cloud-auth", ] } rattler_package_streaming = { version = "0.26", default-features = false } -rattler_repodata_gateway = { version = "0.29", default-features = false } +rattler_repodata_gateway = { version = "0.30", default-features = false } rattler_s3 = { version = "0.2", default-features = false } rattler_shell = { version = "0.27", default-features = false } rattler_solve = { version = "7.2", default-features = false } @@ -276,31 +276,22 @@ version-ranges = { git = "https://github.com/astral-sh/pubgrub", rev = "d8efd776 # `astral-reqwest-middleware` (rattler, rattler-build, uv). reqwest-middleware = { path = "patches/reqwest_middleware_shim" } -# TODO: remove once rattler_config 0.6 is released (see conda/rattler#2557). -# pixi's `Config` is backed by the redesigned `rattler_config::ConfigBase`, -# which is not on crates.io yet. Every rattler crate that shares public types -# with `rattler_config` (directly or transitively) must come from the same -# source, otherwise cargo would build two copies of e.g. -# `rattler_conda_types` and the shared types would not unify. -file_url = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_cache = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_conda_types = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_config = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_digest = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_index = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_lock = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_menuinst = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_networking = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_package_streaming = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_redaction = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_repodata_gateway = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_s3 = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_shell = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_solve = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_upload = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -rattler_virtual_packages = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } -simple_spawn_blocking = { git = "https://github.com/conda/rattler", branch = "claude/rattler-shared-config-design-m8d2gb" } +# TODO: remove once a rattler_build_core built against rattler 0.47 / +# rattler_config 0.6 is published to crates.io (see prefix-dev/rattler-build#2636, +# now merged). The published rattler_build_core (0.2.8) still pins rattler 0.46 / +# rattler_config 0.5.2, whereas pixi now uses the released rattler 0.47 / +# rattler_config 0.6 from crates.io. Point every rattler-build crate in the tree +# at the merged `main`, which is built against those same released crates, so the +# shared rattler / rattler_config types unify. +rattler_build_core = { git = "https://github.com/prefix-dev/rattler-build", branch = "main" } +rattler_build_jinja = { git = "https://github.com/prefix-dev/rattler-build", branch = "main" } +rattler_build_networking = { git = "https://github.com/prefix-dev/rattler-build", branch = "main" } +rattler_build_recipe = { git = "https://github.com/prefix-dev/rattler-build", branch = "main" } +rattler_build_script = { git = "https://github.com/prefix-dev/rattler-build", branch = "main" } +rattler_build_source_cache = { git = "https://github.com/prefix-dev/rattler-build", branch = "main" } +rattler_build_types = { git = "https://github.com/prefix-dev/rattler-build", branch = "main" } +rattler_build_variant_config = { git = "https://github.com/prefix-dev/rattler-build", branch = "main" } +rattler_build_yaml_parser = { git = "https://github.com/prefix-dev/rattler-build", branch = "main" } # Strip debug info from dependencies: faster links, much smaller `target/`, # while keeping full debuggability for our own crates. From 35e91ec590f9228abe31a413fd9aaaa783dfbd36 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 10 Jul 2026 12:08:48 +0000 Subject: [PATCH 5/5] fix: adapt gateway query call sites to RepoDataQueryOutput rattler_repodata_gateway 0.30 changed `Gateway::query(...).await` / `.execute().await` to return a `RepoDataQueryOutput` (repodata records plus non-fatal warnings) instead of `Vec`. Extract `.repodata` at the three call sites that expect a record vector: - pixi_command_dispatcher: keys/solve_conda.rs, ephemeral_env/mod.rs - pixi_cli: exec.rs Behavior-preserving: the previous API returned only records. The pixi_api search path already iterates via the output's `IntoIterator` and needs no change. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01EzYs4p6XJDj9QBcNB4ipR7 --- crates/pixi_cli/src/exec.rs | 5 ++++- crates/pixi_command_dispatcher/src/ephemeral_env/mod.rs | 7 +++++-- crates/pixi_command_dispatcher/src/keys/solve_conda.rs | 4 +++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/pixi_cli/src/exec.rs b/crates/pixi_cli/src/exec.rs index ed55be948d..c9fc857f79 100644 --- a/crates/pixi_cli/src/exec.rs +++ b/crates/pixi_cli/src/exec.rs @@ -252,7 +252,10 @@ pub async fn create_exec_prefix( .into_diagnostic() }) .await - .context("failed to get repodata")?; + .context("failed to get repodata")? + // `execute` now yields a `RepoDataQueryOutput` (repodata_gateway 0.30); + // keep just the repodata records. + .repodata; // Determine virtual packages of the current platform let virtual_packages: Vec = diff --git a/crates/pixi_command_dispatcher/src/ephemeral_env/mod.rs b/crates/pixi_command_dispatcher/src/ephemeral_env/mod.rs index 8963524ece..dcb18407cb 100644 --- a/crates/pixi_command_dispatcher/src/ephemeral_env/mod.rs +++ b/crates/pixi_command_dispatcher/src/ephemeral_env/mod.rs @@ -459,9 +459,12 @@ async fn fetch_binary_repodata( if let Some(reporter) = gateway_reporter { query = query.with_reporter(WrappingGatewayReporter(reporter)); } - query + // `query` now returns a `RepoDataQueryOutput` (repodata_gateway 0.30); + // this helper only exposes the repodata records. + let query_output = query .await - .map_err(|e| EphemeralEnvError::Gateway(Arc::new(e))) + .map_err(|e| EphemeralEnvError::Gateway(Arc::new(e)))?; + Ok(query_output.repodata) } /// Validate that every dependency resolves to a [`BinarySpec`] and diff --git a/crates/pixi_command_dispatcher/src/keys/solve_conda.rs b/crates/pixi_command_dispatcher/src/keys/solve_conda.rs index 0be9c7eb91..fb1ef8636c 100644 --- a/crates/pixi_command_dispatcher/src/keys/solve_conda.rs +++ b/crates/pixi_command_dispatcher/src/keys/solve_conda.rs @@ -281,7 +281,9 @@ impl Key for SolveCondaKey { if let Some(reporter) = gateway_reporter { query = query.with_reporter(WrappingGatewayReporter(reporter)); } - let binary_repodata = query.await?; + // `query` now returns a `RepoDataQueryOutput` (repodata_gateway 0.30); + // we only need the repodata records here. + let binary_repodata = query.await?.repodata; // `binary_repodata.len()` returns the number of subdir buckets, // not the number of records. Sum across them to get the real // count the solver is about to chew through.