diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 05e5db87..5361d2e6 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -32,7 +32,7 @@ jobs: submodules: recursive - uses: dtolnay/rust-toolchain@master with: - toolchain: "1.75.0" + toolchain: "1.80.0" components: clippy,rustfmt - uses: Swatinem/rust-cache@v2 - name: Check @@ -125,7 +125,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: "1.75.0" + toolchain: "1.80.0" targets: ${{ matrix.target }} - name: Install musl-gcc diff --git a/Cargo.lock b/Cargo.lock index 928b353e..f6c3ae00 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -250,6 +250,21 @@ dependencies = [ "slab", ] +[[package]] +name = "async-fd-lock" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7569377d7062165f6f7834d9cb3051974a2d141433cc201c2f94c149e993cccf" +dependencies = [ + "async-trait", + "cfg-if", + "pin-project", + "rustix 0.38.35", + "thiserror", + "tokio", + "windows-sys 0.52.0", +] + [[package]] name = "async-fs" version = "1.6.0" @@ -1386,9 +1401,9 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "file_url" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4602b5420b868957e88e55b927d67e273c764ce9fb6def7369248862928230" +checksum = "31b8d0fe7b11e53d71e1484766a00187bc239910dcacb5bf8909f1f3ffd9b4aa" dependencies = [ "itertools 0.13.0", "percent-encoding", @@ -1480,6 +1495,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" dependencies = [ "autocfg", + "tokio", ] [[package]] @@ -1492,6 +1508,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "fs4" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c6b3bd49c37d2aa3f3f2220233b29a7cd23f79d1fe70e5337d25fb390793de" +dependencies = [ + "fs-err", + "rustix 0.38.35", + "windows-sys 0.52.0", +] + [[package]] name = "fs_extra" version = "1.3.0" @@ -3649,9 +3676,9 @@ dependencies = [ [[package]] name = "rattler" -version = "0.27.7" +version = "0.27.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeb1c7900d09582a363f48ced3edeb1a97ae41c6b8a47e867fd41d61cd01c099" +checksum = "d65df1b9ee6414776fdf552d6d8f80de876babe5d9c64d1604ff5fbea73d0dd6" dependencies = [ "anyhow", "clap", @@ -3669,10 +3696,10 @@ dependencies = [ "once_cell", "parking_lot", "rattler_cache", - "rattler_conda_types 0.27.3", - "rattler_digest 1.0.1", - "rattler_networking 0.21.2", - "rattler_package_streaming 0.22.4", + "rattler_conda_types 0.27.5", + "rattler_digest 1.0.2", + "rattler_networking 0.21.4", + "rattler_package_streaming 0.22.6", "rattler_shell", "reflink-copy", "regex", @@ -3731,12 +3758,13 @@ dependencies = [ "petgraph", "ratatui", "rattler", - "rattler_conda_types 0.27.3", - "rattler_digest 1.0.1", + "rattler_cache", + "rattler_conda_types 0.27.5", + "rattler_digest 1.0.2", "rattler_index", "rattler_installs_packages", - "rattler_networking 0.21.2", - "rattler_package_streaming 0.22.4", + "rattler_networking 0.21.4", + "rattler_package_streaming 0.22.6", "rattler_redaction", "rattler_repodata_gateway", "rattler_shell", @@ -3780,22 +3808,26 @@ dependencies = [ [[package]] name = "rattler_cache" -version = "0.1.9" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cb85c55b25504c924bb3118d550e0f0faa98ae6d2c1f1649f2542d8b283902e" +checksum = "be8699896b5cc495af86937024a1e6fead33fc921efec171e13348cee5ef7f86" dependencies = [ "anyhow", + "dashmap", "digest", "dirs", + "fs4 0.9.1", + "futures", "fxhash", "itertools 0.13.0", "parking_lot", - "rattler_conda_types 0.27.3", - "rattler_digest 1.0.1", - "rattler_networking 0.21.2", - "rattler_package_streaming 0.22.4", + "rattler_conda_types 0.27.5", + "rattler_digest 1.0.2", + "rattler_networking 0.21.4", + "rattler_package_streaming 0.22.6", "reqwest 0.12.7", "reqwest-middleware", + "simple_spawn_blocking", "thiserror", "tokio", "tracing", @@ -3838,9 +3870,9 @@ dependencies = [ [[package]] name = "rattler_conda_types" -version = "0.27.3" +version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fd487490f51a206e9551e109ccbcdb3d1b3755fbe9c51aa55483c15299a7417" +checksum = "aac998898b49659f9fa9bdaad9e6c4272cd5306a704c4f1f2928dcdfff6ea8bd" dependencies = [ "chrono", "dirs", @@ -3853,8 +3885,8 @@ dependencies = [ "lazy-regex", "nom", "purl", - "rattler_digest 1.0.1", - "rattler_macros 1.0.1", + "rattler_digest 1.0.2", + "rattler_macros 1.0.2", "rattler_redaction", "regex", "serde", @@ -3890,9 +3922,9 @@ dependencies = [ [[package]] name = "rattler_digest" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d699fe089907cc0ca66966f6b94e0dc04792a1451b2a60ba49c0abb75fba33da" +checksum = "a87e1ed2c7df1dbbfaa79d8f520c347d511231c77f4dd5327a6c389758a98db0" dependencies = [ "blake2", "digest", @@ -3907,14 +3939,14 @@ dependencies = [ [[package]] name = "rattler_index" -version = "0.19.25" +version = "0.19.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23265b2e3cc753c95d173cb0e42ec1b0198a4d298c5d196b5e19083822724994" +checksum = "f31343cdaeb4ae1c5bfa5e0c701f6feb4b7d1737d972068b75b0b2947c13474f" dependencies = [ "fs-err", - "rattler_conda_types 0.27.3", - "rattler_digest 1.0.1", - "rattler_package_streaming 0.22.4", + "rattler_conda_types 0.27.5", + "rattler_digest 1.0.2", + "rattler_package_streaming 0.22.6", "serde_json", "tracing", "walkdir", @@ -3941,7 +3973,7 @@ dependencies = [ "elsa", "flate2", "fs-err", - "fs4", + "fs4 0.8.4", "fs_extra", "futures", "html-escape", @@ -3993,9 +4025,9 @@ dependencies = [ [[package]] name = "rattler_macros" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18011e84fcc8dba03a4af5b70cbb99362968cdace525139df430b4f268ef58e0" +checksum = "0306a96eb7216c786fa6234fd26207bf3769cbb48b2373d682eabb36ff11c175" dependencies = [ "quote", "syn 2.0.77", @@ -4030,9 +4062,9 @@ dependencies = [ [[package]] name = "rattler_networking" -version = "0.21.2" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c53c13a325db9d307886a6a31c3c88a3126b006fe618974b528b6dcf1943ece1" +checksum = "4ada69629cc3ea204055f4d13604b32cb108fca456cc87d97d4280f041ac5708" dependencies = [ "anyhow", "async-trait", @@ -4082,17 +4114,17 @@ dependencies = [ [[package]] name = "rattler_package_streaming" -version = "0.22.4" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df5c10938fee28ecbeb7ab1c4d499fe6a4d5be5db7d72007a0fccac81ae95d34" +checksum = "20c889bfc333fc6e8ea67fc1731a4da3e51f74e3231f770dc3a1fe6ee1fc23a8" dependencies = [ "bzip2", "chrono", "futures-util", "num_cpus", - "rattler_conda_types 0.27.3", - "rattler_digest 1.0.1", - "rattler_networking 0.21.2", + "rattler_conda_types 0.27.5", + "rattler_digest 1.0.2", + "rattler_networking 0.21.4", "rattler_redaction", "reqwest 0.12.7", "reqwest-middleware", @@ -4110,9 +4142,9 @@ dependencies = [ [[package]] name = "rattler_redaction" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b8739ebf209f017d70f4a27b2726358bade979cc3327b1765163c93a18d46f" +checksum = "6a8b3a430398cc4ecd0350204087377bc31d977dfd897d3b6930f195f39c515b" dependencies = [ "reqwest 0.12.7", "reqwest-middleware", @@ -4121,12 +4153,13 @@ dependencies = [ [[package]] name = "rattler_repodata_gateway" -version = "0.21.9" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "223d58601452dc8e169393666a31377e4583e2f7fc1c82a626dac31c353534f1" +checksum = "35eb42953ae7dba91aa53881667e8c6541c1e265a10a8b66a96c6870d1a70d39" dependencies = [ "anyhow", "async-compression", + "async-fd-lock", "async-trait", "blake2", "bytes", @@ -4150,9 +4183,9 @@ dependencies = [ "parking_lot", "pin-project-lite", "rattler_cache", - "rattler_conda_types 0.27.3", - "rattler_digest 1.0.1", - "rattler_networking 0.21.2", + "rattler_conda_types 0.27.5", + "rattler_digest 1.0.2", + "rattler_networking 0.21.4", "rattler_redaction", "reqwest 0.12.7", "reqwest-middleware", @@ -4174,14 +4207,14 @@ dependencies = [ [[package]] name = "rattler_shell" -version = "0.21.7" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9d5ae403e5aa7bc3068c1d649d80e807b88f18ef82d6e82df0313004b80d2d" +checksum = "7c2c4ea6b51960de7c37330b80446a97acfd7d2cf24aac40131013afd1c2e902" dependencies = [ "enum_dispatch", "indexmap 2.5.0", "itertools 0.13.0", - "rattler_conda_types 0.27.3", + "rattler_conda_types 0.27.5", "serde_json", "shlex", "sysinfo", @@ -4192,15 +4225,15 @@ dependencies = [ [[package]] name = "rattler_solve" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cd622a01da7534b598c3ad7bbc8d0f979438236757087f4dae04ce7f2a1dd8f" +checksum = "b907ab9441c5b1617fd0b640f4218c14aec4e09b8e730688330db2710b7e3738" dependencies = [ "chrono", "futures", "itertools 0.13.0", - "rattler_conda_types 0.27.3", - "rattler_digest 1.0.1", + "rattler_conda_types 0.27.5", + "rattler_digest 1.0.2", "resolvo 0.7.0", "serde", "tempfile", @@ -4211,16 +4244,16 @@ dependencies = [ [[package]] name = "rattler_virtual_packages" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf0ffd2b8bf06758524325e52ed45749fb20fe23bbaa818a56f5482855e4ef7" +checksum = "ae3df3470a9b4fbbece991c5d3969efabb375e696f1f138111e69221cbd19733" dependencies = [ "archspec", "libloading", "nom", "once_cell", "plist", - "rattler_conda_types 0.27.3", + "rattler_conda_types 0.27.5", "regex", "serde", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index b60214a0..65deb704 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ readme = "README.md" description = "A fast CLI tool to build conda packages on Windows, macOS and Linux" documentation = "https://prefix-dev.github.io/rattler-build" default-run = "rattler-build" +rust-version = "1.80.0" [features] default = ['native-tls', 'recipe-generation'] @@ -44,27 +45,6 @@ required-features = ["recipe-generation"] [dependencies] serde = { version = "1.0.209", features = ["derive"] } serde_yaml = "0.9.34" -rattler = { version = "0.27.7", default-features = false, features = [ - "cli-tools", - "indicatif", -] } -rattler_conda_types = { version = "0.27.3", default-features = false } -rattler_digest = { version = "1.0.1", default-features = false, features = ["serde"] } -rattler_index = { version = "0.19.25", default-features = false } -rattler_networking = { version = "0.21.2", default-features = false } -rattler_redaction = { version = "0.1.1" } -rattler_repodata_gateway = { version = "0.21.9", default-features = false, features = [ - "gateway", -] } -rattler_shell = { version = "0.21.7", default-features = false, features = [ - "sysinfo", -] } -rattler_solve = { version = "1.0.4", default-features = false, features = [ - "resolvo", - "serde", -] } -rattler_virtual_packages = { version = "1.1.0", default-features = false } -rattler_package_streaming = { version = "0.22.4", default-features = false } anyhow = "1.0.86" walkdir = "2.5.0" sha2 = "0.10.8" @@ -148,6 +128,20 @@ regex = "1.10.6" clap-markdown = { version = "=0.1.3", optional = true } async-recursion = "1.1.1" +# Rattler crates +rattler = { version = "0.27.10", default-features = false, features = ["cli-tools", "indicatif"] } +rattler_cache = { version = "0.2.2", default-features = false } +rattler_conda_types = { version = "0.27.5", default-features = false } +rattler_digest = { version = "1.0.2", default-features = false, features = ["serde"] } +rattler_index = { version = "0.19.27", default-features = false } +rattler_networking = { version = "0.21.4", default-features = false } +rattler_redaction = { version = "0.1.2" } +rattler_repodata_gateway = { version = "0.21.12", default-features = false, features = ["gateway"] } +rattler_shell = { version = "0.22.0", default-features = false, features = ["sysinfo"] } +rattler_solve = { version = "1.0.6", default-features = false, features = ["resolvo", "serde"] } +rattler_virtual_packages = { version = "1.1.3", default-features = false } +rattler_package_streaming = { version = "0.22.6", default-features = false } + [dev-dependencies] insta = { version = "1.39.0", features = ["yaml"] } rstest = "0.21.0" @@ -184,14 +178,16 @@ pre-build = [ clap-markdown = { git = "https://github.com/ruben-arts/clap-markdown", branch = "main" } -# rattler = { path = "../rattler/crates/rattler" } -# rattler_conda_types = { path = "../rattler/crates/rattler_conda_types" } -# rattler_digest = { path = "../rattler/crates/rattler_digest" } -# rattler_index = { path = "../rattler/crates/rattler_index" } -# rattler_networking = { path = "../rattler/crates/rattler_networking" } -# rattler_repodata_gateway = { path = "../rattler/crates/rattler_repodata_gateway" } -# rattler_shell = { path = "../rattler/crates/rattler_shell" } -# rattler_solve = { path = "../rattler/crates/rattler_solve" } -# rattler_virtual_packages = { path = "../rattler/crates/rattler_virtual_packages" } -# rattler_package_streaming = { path = "../rattler/crates/rattler_package_streaming" } +#rattler = { path = "../rattler/crates/rattler" } +#rattler_cache = { path = "../rattler/crates/rattler_cache" } +#rattler_conda_types = { path = "../rattler/crates/rattler_conda_types" } +#rattler_digest = { path = "../rattler/crates/rattler_digest" } +#rattler_index = { path = "../rattler/crates/rattler_index" } +#rattler_networking = { path = "../rattler/crates/rattler_networking" } +#rattler_repodata_gateway = { path = "../rattler/crates/rattler_repodata_gateway" } +#rattler_shell = { path = "../rattler/crates/rattler_shell" } +#rattler_solve = { path = "../rattler/crates/rattler_solve" } +#rattler_redaction = { path = "../rattler/crates/rattler_redaction" } +#rattler_virtual_packages = { path = "../rattler/crates/rattler_virtual_packages" } +#rattler_package_streaming = { path = "../rattler/crates/rattler_package_streaming" } #clap-markdown = { path = "../clap-markdown" } diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 0d9bc2db..619818c9 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -191,8 +191,10 @@ Build a package from a recipe - `--package-format ` - The package format to use for the build. Can be one of `tar-bz2` or `conda`. -You can also add a compression level to the package format, e.g. `tar-bz2:` (from 1 to 9) or `conda:` (from -7 to 22). + The package format to use for the build. Can be one of `tar-bz2` or +`conda`. You can also add a compression level to the package format, +e.g. `tar-bz2:` (from 1 to 9) or `conda:` (from -7 to +22). - Default value: `conda` diff --git a/pixi.lock b/pixi.lock index 84834f49..858d5b2e 100644 --- a/pixi.lock +++ b/pixi.lock @@ -7,16 +7,17 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/_sysroot_linux-64_curr_repodata_hack-3-h69a702a_16.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils-2.40-h4852527_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.40-ha1999f0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.40-hdade7a5_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py311hb755f60_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py312h2ec8cdc_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.28.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/c-compiler-1.6.0-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.2.2-hbcca054_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.16.0-py311hb3a22ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.17.0-py312h06ac9bb_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cfgv-3.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.27.6-hcfe8598_0.conda @@ -41,7 +42,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.5.36-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-2.6.32-he073ed8_17.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-3.10.0-h4a8ded7_16.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-hf3520f5_1.conda @@ -50,21 +51,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-14.1.0-h77fa898_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-12.3.0-h0223996_107.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h77fa898_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.1.0-h69a702a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-13.2.0-hca663fb_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h77fa898_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-14.1.0-h77fa898_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.58.0-h47da74e_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-12.3.0-hb8811af_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.3-h2797004_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.46.1-hadc24fc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-14.1.0-hc0a3c3a_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-12.3.0-h0223996_107.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-hc0a3c3a_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.48.0-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-h4ab18f5_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-h4ab18f5_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/make-4.3-hd18ef5c_1.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h59595ed_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.8.0-pyhd8ed1ab_0.conda @@ -78,26 +81,26 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pycparser-2.22-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.9-hb806964_0_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.11-4_cp311.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.1-py311h459d7ec_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.3-hab00c5b_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-5_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.2-py312h66e93f0_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.76.0-h70c747d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.76.0-h2c6d0dc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rust-1.80.1-h0a17960_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.80.1-h2c6d0dc_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-70.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/syrupy-4.6.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.12-he073ed8_17.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.17-h4a8ded7_16.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.0.1-py311h9547e67_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.0.1-py312h8572e83_4.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.26.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h7f98852_2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.19.0-py311hd4cff14_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.23.0-py312hef9b889_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda osx-64: - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py39h840bb9f_1.conda @@ -183,8 +186,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/rust-1.76.0-h7e1429e_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-apple-darwin-1.76.0-h38e4360_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rust-1.80.1-h6c54e5d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-apple-darwin-1.80.1-h38e4360_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-70.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/syrupy-4.6.1-pyhd8ed1ab_0.conda @@ -287,8 +290,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rust-1.76.0-h4ff7c5d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-aarch64-apple-darwin-1.76.0-hf6ec828_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rust-1.80.1-h4ff7c5d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-aarch64-apple-darwin-1.80.1-hf6ec828_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-70.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/syrupy-4.6.1-pyhd8ed1ab_0.conda @@ -366,8 +369,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.9-4_cp39.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0.1-py39ha55989b_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/rust-1.76.0-hf8d6059_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-pc-windows-msvc-1.76.0-h17fc481_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/rust-1.80.1-hf8d6059_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-pc-windows-msvc-1.80.1-h17fc481_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-70.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/syrupy-4.6.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda @@ -395,14 +398,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.14.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py311hb755f60_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py312h2ec8cdc_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.2.2-hbcca054_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.0-h3faef2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.0-hebfffa5_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cairocffi-1.6.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/cairosvg-2.7.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.16.0-py311hb3a22ac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.17.0-py312h06ac9bb_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 @@ -418,7 +421,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/fonts-conda-forge-1-0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/freetype-2.12.1-h267a509_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ghp-import-2.1.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.7-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-resources-6.4.0-pyhd8ed1ab_0.conda @@ -427,26 +430,28 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.16-hb7c19ff_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-hf3520f5_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.0.0-h27087fc_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.20-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.21-h4bc722e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h77fa898_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.80.2-hf974151_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h77fa898_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-14.1.0-h77fa898_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.1.0-h69a702a_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.80.3-h315aac3_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-14.1.0-h77fa898_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.17-hd590300_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.0.0-hd590300_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.43-h2797004_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.3-h2797004_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.46.1-hadc24fc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-14.1.0-hc0a3c3a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-hc0a3c3a_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.6.0-h1dd3fc0_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.6.0-h46a8edc_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libwebp-base-1.4.0-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.15-h0b41bf4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.16-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-h4ab18f5_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-h4ab18f5_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-3.6-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py311h459d7ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py312h66e93f0_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mergedeep-1.3.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/mike-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mkdocs-1.5.3-pyhd8ed1ab_0.conda @@ -458,8 +463,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/paginate-0.5.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.43-hcad00b1_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-10.3.0-py311h18e6fac_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.44-hba22ea6_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pillow-10.4.0-py312h287a98d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pixman-0.43.2-h59595ed_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pthread-stubs-0.4-h36c2ea0_1001.tar.bz2 @@ -469,14 +474,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/pymdown-extensions-10.8.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.9-hb806964_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.3-hab00c5b_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.9.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-5_cp312.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytz-2024.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.1-py311h459d7ec_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.2-py312h66e93f0_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pyyaml-env-tag-0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2024.5.15-py311h331c9d8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/regex-2024.7.24-py312h66e93f0_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.32.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-70.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2 @@ -487,12 +492,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/verspec-0.1.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/watchdog-4.0.1-py311h38be061_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/watchdog-5.0.1-py312h7900ff3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-kbproto-1.0.7-h7f98852_1002.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libice-1.1.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libsm-1.2.4-h7391055_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.9-h8ee46fc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.9-hb711507_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.11-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.3-h7f98852_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxext-1.3.4-h0b41bf4_2.conda @@ -503,7 +508,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h7f98852_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-h4ab18f5_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.1-h4ab18f5_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda osx-64: - conda: https://conda.anaconda.org/conda-forge/noarch/babel-2.14.0-pyhd8ed1ab_0.conda @@ -837,6 +842,20 @@ packages: license_family: BSD size: 23621 timestamp: 1650670423406 +- kind: conda + name: _sysroot_linux-64_curr_repodata_hack + version: '3' + build: h69a702a_16 + build_number: 16 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/_sysroot_linux-64_curr_repodata_hack-3-h69a702a_16.conda + sha256: 6ac30acdbfd3136ee7a1de28af4355165291627e905715611726e674499b0786 + md5: 1c005af0c6ff22814b7c52ee448d4bea + license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later AND MPL-2.0 + license_family: GPL + size: 20798 + timestamp: 1720621358501 - kind: conda name: babel version: 2.14.0 @@ -924,23 +943,24 @@ packages: - kind: conda name: brotli-python version: 1.1.0 - build: py311hb755f60_1 - build_number: 1 + build: py312h2ec8cdc_2 + build_number: 2 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py311hb755f60_1.conda - sha256: 559093679e9fdb6061b7b80ca0f9a31fe6ffc213f1dae65bc5c82e2cd1a94107 - md5: cce9e7c3f1c307f2a5fb08a2922d6164 - depends: - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 + url: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py312h2ec8cdc_2.conda + sha256: f2a59ccd20b4816dea9a2a5cb917eb69728271dbf1aeab4e1b7e609330a50b6f + md5: b0b867af6fc74b2a0aa206da29c0f3cf + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libstdcxx >=13 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 constrains: - - libbrotlicommon 1.1.0 hd590300_1 + - libbrotlicommon 1.1.0 hb9d3cd8_2 license: MIT license_family: MIT - size: 351340 - timestamp: 1695990160360 + size: 349867 + timestamp: 1725267732089 - kind: conda name: brotli-python version: 1.1.0 @@ -1205,35 +1225,6 @@ packages: license: LGPL-2.1-only or MPL-1.1 size: 1520159 timestamp: 1697029136038 -- kind: conda - name: cairo - version: 1.18.0 - build: h3faef2a_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.0-h3faef2a_0.conda - sha256: 142e2639a5bc0e99c44d76f4cc8dce9c6a2d87330c4beeabb128832cd871a86e - md5: f907bb958910dc404647326ca80c263e - depends: - - fontconfig >=2.14.2,<3.0a0 - - fonts-conda-ecosystem - - freetype >=2.12.1,<3.0a0 - - icu >=73.2,<74.0a0 - - libgcc-ng >=12 - - libglib >=2.78.0,<3.0a0 - - libpng >=1.6.39,<1.7.0a0 - - libstdcxx-ng >=12 - - libxcb >=1.15,<1.16.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - pixman >=0.42.2,<1.0a0 - - xorg-libice >=1.1.1,<2.0a0 - - xorg-libsm >=1.2.4,<2.0a0 - - xorg-libx11 >=1.8.6,<2.0a0 - - xorg-libxext >=1.3.4,<2.0a0 - - xorg-libxrender >=0.9.11,<0.10.0a0 - - zlib - license: LGPL-2.1-only or MPL-1.1 - size: 982351 - timestamp: 1697028423052 - kind: conda name: cairo version: 1.18.0 @@ -1280,6 +1271,37 @@ packages: license: LGPL-2.1-only or MPL-1.1 size: 897919 timestamp: 1697028755150 +- kind: conda + name: cairo + version: 1.18.0 + build: hebfffa5_3 + build_number: 3 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/cairo-1.18.0-hebfffa5_3.conda + sha256: aee5b9e6ef71cdfb2aee9beae3ea91910ca761c01c0ef32052e3f94a252fa173 + md5: fceaedf1cdbcb02df9699a0d9b005292 + depends: + - __glibc >=2.17,<3.0.a0 + - fontconfig >=2.14.2,<3.0a0 + - fonts-conda-ecosystem + - freetype >=2.12.1,<3.0a0 + - icu >=75.1,<76.0a0 + - libgcc-ng >=12 + - libglib >=2.80.3,<3.0a0 + - libpng >=1.6.43,<1.7.0a0 + - libstdcxx-ng >=12 + - libxcb >=1.16,<1.17.0a0 + - libzlib >=1.3.1,<2.0a0 + - pixman >=0.43.2,<1.0a0 + - xorg-libice >=1.1.1,<2.0a0 + - xorg-libsm >=1.2.4,<2.0a0 + - xorg-libx11 >=1.8.9,<2.0a0 + - xorg-libxext >=1.3.4,<2.0a0 + - xorg-libxrender >=0.9.11,<0.10.0a0 + - zlib + license: LGPL-2.1-only or MPL-1.1 + size: 983604 + timestamp: 1721138900054 - kind: conda name: cairocffi version: 1.6.1 @@ -1447,24 +1469,6 @@ packages: license_family: MIT size: 292511 timestamp: 1696002194472 -- kind: conda - name: cffi - version: 1.16.0 - build: py311hb3a22ac_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.16.0-py311hb3a22ac_0.conda - sha256: b71c94528ca0c35133da4b7ef69b51a0b55eeee570376057f3d2ad60c3ab1444 - md5: b3469563ac5e808b0cd92810d0697043 - depends: - - libffi >=3.4,<4.0a0 - - libgcc-ng >=12 - - pycparser - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - license: MIT - license_family: MIT - size: 300207 - timestamp: 1696001873452 - kind: conda name: cffi version: 1.16.0 @@ -1501,6 +1505,26 @@ packages: license_family: MIT size: 236120 timestamp: 1696002149834 +- kind: conda + name: cffi + version: 1.17.0 + build: py312h06ac9bb_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.17.0-py312h06ac9bb_1.conda + sha256: 397f588c30dd1a30236d289d8dc7f3c34cd71a498dc66d20450393014594cf4d + md5: db9bdbaee0f524ead0471689f002781e + depends: + - __glibc >=2.17,<3.0.a0 + - libffi >=3.4,<4.0a0 + - libgcc >=13 + - pycparser + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + size: 294242 + timestamp: 1724956485789 - kind: conda name: cfgv version: 3.3.1 @@ -1869,7 +1893,7 @@ packages: - libgcc-ng >=12 - libstdcxx-ng >=12 - libuv >=1.46.0,<2.0a0 - - libzlib >=1.2.13,<1.3.0a0 + - libzlib >=1.2.13,<2.0.0a0 - ncurses >=6.4,<7.0a0 - rhash >=1.4.4,<2.0a0 - xz >=5.2.6,<6.0a0 @@ -2400,7 +2424,7 @@ packages: - freetype >=2.12.1,<3.0a0 - libgcc-ng >=12 - libuuid >=2.32.1,<3.0a0 - - libzlib >=1.2.13,<1.3.0a0 + - libzlib >=1.2.13,<2.0.0a0 license: MIT license_family: MIT size: 272010 @@ -2565,7 +2589,7 @@ packages: depends: - libgcc-ng >=12 - libpng >=1.6.39,<1.7.0a0 - - libzlib >=1.2.13,<1.3.0a0 + - libzlib >=1.2.13,<2.0.0a0 license: GPL-2.0-only OR FTL size: 634972 timestamp: 1694615932610 @@ -2945,21 +2969,6 @@ packages: license_family: BSD size: 29304 timestamp: 1710260169322 -- kind: conda - name: icu - version: '73.2' - build: h59595ed_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda - sha256: e12fd90ef6601da2875ebc432452590bc82a893041473bc1c13ef29001a73ea8 - md5: cc47e1facc155f91abd89b11e48e72ff - depends: - - libgcc-ng >=12 - - libstdcxx-ng >=12 - license: MIT - license_family: MIT - size: 12089150 - timestamp: 1692900650789 - kind: conda name: icu version: '73.2' @@ -3000,6 +3009,22 @@ packages: license_family: MIT size: 11787527 timestamp: 1692901622519 +- kind: conda + name: icu + version: '75.1' + build: he02047a_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda + sha256: 71e750d509f5fa3421087ba88ef9a7b9be11c53174af3aa4d06aff4c18b38e8e + md5: 8b189310083baabfb622af68fd9d3ae3 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: MIT + license_family: MIT + size: 12129203 + timestamp: 1720853576813 - kind: conda name: identify version: 2.5.36 @@ -3148,20 +3173,22 @@ packages: timestamp: 1715127275924 - kind: conda name: kernel-headers_linux-64 - version: 2.6.32 - build: he073ed8_17 - build_number: 17 + version: 3.10.0 + build: h4a8ded7_16 + build_number: 16 subdir: noarch noarch: generic - url: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-2.6.32-he073ed8_17.conda - sha256: fb39d64b48f3d9d1acc3df208911a41f25b6a00bd54935d5973b4739a9edd5b6 - md5: d731b543793afc0433c4fd593e693fce + url: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-3.10.0-h4a8ded7_16.conda + sha256: a55044e0f61058a5f6bab5e1dd7f15a1fa7a08ec41501dbfca5ab0fc50b9c0c1 + md5: ff7f38675b226cfb855aebfc32a13e31 + depends: + - _sysroot_linux-64_curr_repodata_hack 3.* constrains: - - sysroot_linux-64 ==2.12 + - sysroot_linux-64 ==2.17 license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later AND MPL-2.0 license_family: GPL - size: 710627 - timestamp: 1708000830116 + size: 944344 + timestamp: 1720621422017 - kind: conda name: keyutils version: 1.6.1 @@ -3645,18 +3672,19 @@ packages: timestamp: 1711197066985 - kind: conda name: libdeflate - version: '1.20' - build: hd590300_0 + version: '1.21' + build: h4bc722e_0 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.20-hd590300_0.conda - sha256: f8e0f25c382b1d0b87a9b03887a34dbd91485453f1ea991fef726dba57373612 - md5: 8e88f9389f1165d7c0936fe40d9a9a79 + url: https://conda.anaconda.org/conda-forge/linux-64/libdeflate-1.21-h4bc722e_0.conda + sha256: 728c24ce835700bfdfdf106bf04233fdb040a61ca4ecfd3f41b46fa90cd4f971 + md5: 36ce76665bf67f5aac36be7a0d21b7f3 depends: + - __glibc >=2.17,<3.0.a0 - libgcc-ng >=12 license: MIT license_family: MIT - size: 71500 - timestamp: 1711196523408 + size: 71163 + timestamp: 1722820138782 - kind: conda name: libedit version: 3.1.20191231 @@ -3878,6 +3906,25 @@ packages: license: Apache 2.0 size: 531143 timestamp: 1527899216421 +- kind: conda + name: libgcc + version: 14.1.0 + build: h77fa898_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-14.1.0-h77fa898_1.conda + sha256: 10fa74b69266a2be7b96db881e18fa62cfa03082b65231e8d652e897c4b335a3 + md5: 002ef4463dd1e2b44a94a4ace468f5d2 + depends: + - _libgcc_mutex 0.1 conda_forge + - _openmp_mutex >=4.5 + constrains: + - libgomp 14.1.0 h77fa898_1 + - libgcc-ng ==14.1.0=*_1 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 846380 + timestamp: 1724801836552 - kind: conda name: libgcc-devel_linux-64 version: 12.3.0 @@ -3894,22 +3941,19 @@ packages: timestamp: 1715016464312 - kind: conda name: libgcc-ng - version: 13.2.0 - build: h77fa898_7 - build_number: 7 + version: 14.1.0 + build: h69a702a_1 + build_number: 1 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h77fa898_7.conda - sha256: 62af2b89acbe74a21606c8410c276e57309c0a2ab8a9e8639e3c8131c0b60c92 - md5: 72ec1b1b04c4d15d4204ece1ecea5978 + url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.1.0-h69a702a_1.conda + sha256: b91f7021e14c3d5c840fbf0dc75370d6e1f7c7ff4482220940eaafb9c64613b7 + md5: 1efc0ad219877a73ef977af7dbb51f17 depends: - - _libgcc_mutex 0.1 conda_forge - - _openmp_mutex >=4.5 - constrains: - - libgomp 13.2.0 h77fa898_7 + - libgcc 14.1.0 h77fa898_1 license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL - size: 775806 - timestamp: 1715016057793 + size: 52170 + timestamp: 1724801842101 - kind: conda name: libgfortran version: 5.0.0 @@ -4083,38 +4127,40 @@ packages: timestamp: 1715252979767 - kind: conda name: libglib - version: 2.80.2 - build: hf974151_0 + version: 2.80.3 + build: h315aac3_2 + build_number: 2 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.80.2-hf974151_0.conda - sha256: 93e03b6cf4765bc06d64fa3dac65f22c53ae4a30247bb0e2dea0bd9c47a3fb26 - md5: 72724f6a78ecb15559396966226d5838 + url: https://conda.anaconda.org/conda-forge/linux-64/libglib-2.80.3-h315aac3_2.conda + sha256: 7470e664b780b91708bed356cc634874dfc3d6f17cbf884a1d6f5d6d59c09f91 + md5: b0143a3e98136a680b728fdf9b42a258 depends: + - __glibc >=2.17,<3.0.a0 - libffi >=3.4,<4.0a0 - libgcc-ng >=12 - libiconv >=1.17,<2.0a0 - - libzlib >=1.2.13,<2.0.0a0 - - pcre2 >=10.43,<10.44.0a0 + - libzlib >=1.3.1,<2.0a0 + - pcre2 >=10.44,<10.45.0a0 constrains: - - glib 2.80.2 *_0 + - glib 2.80.3 *_2 license: LGPL-2.1-or-later - size: 3912673 - timestamp: 1715252654366 + size: 3922900 + timestamp: 1723208802469 - kind: conda name: libgomp - version: 13.2.0 - build: h77fa898_7 - build_number: 7 + version: 14.1.0 + build: h77fa898_1 + build_number: 1 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h77fa898_7.conda - sha256: 781444fa069d3b50e8ed667b750571cacda785761c7fc2a89ece1ac49693d4ad - md5: abf3fec87c2563697defa759dec3d639 + url: https://conda.anaconda.org/conda-forge/linux-64/libgomp-14.1.0-h77fa898_1.conda + sha256: c96724c8ae4ee61af7674c5d9e5a3fbcf6cd887a40ad5a52c99aa36f1d4f9680 + md5: 23c255b008c4f2ae008f81edcabaca89 depends: - _libgcc_mutex 0.1 conda_forge license: GPL-3.0-only WITH GCC-exception-3.1 license_family: GPL - size: 422336 - timestamp: 1715015995979 + size: 460218 + timestamp: 1724801743478 - kind: conda name: libiconv version: '1.17' @@ -4323,7 +4369,7 @@ packages: - libev >=4.33,<5.0a0 - libgcc-ng >=12 - libstdcxx-ng >=12 - - libzlib >=1.2.13,<1.3.0a0 + - libzlib >=1.2.13,<2.0.0a0 - openssl >=3.2.0,<4.0a0 license: MIT license_family: MIT @@ -4424,7 +4470,7 @@ packages: md5: 009981dd9cfcaa4dbfa25ffaed86bcae depends: - libgcc-ng >=12 - - libzlib >=1.2.13,<1.3.0a0 + - libzlib >=1.2.13,<2.0.0a0 license: zlib-acknowledgement size: 288221 timestamp: 1708780443939 @@ -4469,20 +4515,6 @@ packages: license: Unlicense size: 824794 timestamp: 1713367748819 -- kind: conda - name: libsqlite - version: 3.45.3 - build: h2797004_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.3-h2797004_0.conda - sha256: e2273d6860eadcf714a759ffb6dc24a69cfd01f2a0ea9d6c20f86049b9334e0c - md5: b3316cbe90249da4f8e84cd66e1cc55b - depends: - - libgcc-ng >=12 - - libzlib >=1.2.13,<1.3.0a0 - license: Unlicense - size: 859858 - timestamp: 1713367435849 - kind: conda name: libsqlite version: 3.45.3 @@ -4511,6 +4543,21 @@ packages: license: Unlicense size: 870518 timestamp: 1713367888406 +- kind: conda + name: libsqlite + version: 3.46.1 + build: hadc24fc_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.46.1-hadc24fc_0.conda + sha256: 9851c049abafed3ee329d6c7c2033407e2fc269d33a75c071110ab52300002b0 + md5: 36f79405ab16bf271edb55b213836dac + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - libzlib >=1.3.1,<2.0a0 + license: Unlicense + size: 865214 + timestamp: 1725353659783 - kind: conda name: libssh2 version: 1.11.0 @@ -4521,7 +4568,7 @@ packages: md5: 1f5a58e686b13bcfde88b93f547d23fe depends: - libgcc-ng >=12 - - libzlib >=1.2.13,<1.3.0a0 + - libzlib >=1.2.13,<2.0.0a0 - openssl >=3.1.1,<4.0a0 license: BSD-3-Clause license_family: BSD @@ -4575,6 +4622,21 @@ packages: license_family: BSD size: 259556 timestamp: 1685837820566 +- kind: conda + name: libstdcxx + version: 14.1.0 + build: hc0a3c3a_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-14.1.0-hc0a3c3a_1.conda + sha256: 44decb3d23abacf1c6dd59f3c152a7101b7ca565b4ef8872804ceaedcc53a9cd + md5: 9dbb9699ea467983ba8a4ba89b08b066 + depends: + - libgcc 14.1.0 h77fa898_1 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 3892781 + timestamp: 1724801863728 - kind: conda name: libstdcxx-devel_linux-64 version: 12.3.0 @@ -4647,25 +4709,26 @@ packages: - kind: conda name: libtiff version: 4.6.0 - build: h1dd3fc0_3 - build_number: 3 + build: h46a8edc_4 + build_number: 4 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.6.0-h1dd3fc0_3.conda - sha256: fc3b210f9584a92793c07396cb93e72265ff3f1fa7ca629128bf0a50d5cb15e4 - md5: 66f03896ffbe1a110ffda05c7a856504 + url: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.6.0-h46a8edc_4.conda + sha256: 8d42dd7c6602187d4351fc3b69ff526f1c262bfcbfd6ce05d06008f4e0b99b58 + md5: a7e3a62981350e232e0e7345b5aea580 depends: + - __glibc >=2.17,<3.0.a0 - lerc >=4.0.0,<5.0a0 - - libdeflate >=1.20,<1.21.0a0 + - libdeflate >=1.21,<1.22.0a0 - libgcc-ng >=12 - libjpeg-turbo >=3.0.0,<4.0a0 - libstdcxx-ng >=12 - - libwebp-base >=1.3.2,<2.0a0 - - libzlib >=1.2.13,<1.3.0a0 + - libwebp-base >=1.4.0,<2.0a0 + - libzlib >=1.3.1,<2.0a0 - xz >=5.2.6,<6.0a0 - - zstd >=1.5.5,<1.6.0a0 + - zstd >=1.5.6,<1.6.0a0 license: HPND - size: 282688 - timestamp: 1711217970425 + size: 282236 + timestamp: 1722871642189 - kind: conda name: libtiff version: 4.6.0 @@ -4818,23 +4881,6 @@ packages: license_family: BSD size: 438953 timestamp: 1713199854503 -- kind: conda - name: libxcb - version: '1.15' - build: h0b41bf4_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.15-h0b41bf4_0.conda - sha256: a670902f0a3173a466c058d2ac22ca1dd0df0453d3a80e0212815c20a16b0485 - md5: 33277193f5b92bad9fdd230eb700929c - depends: - - libgcc-ng >=12 - - pthread-stubs - - xorg-libxau - - xorg-libxdmcp - license: MIT - license_family: MIT - size: 384238 - timestamp: 1682082368177 - kind: conda name: libxcb version: '1.15' @@ -4885,6 +4931,25 @@ packages: license_family: MIT size: 334770 timestamp: 1682082734262 +- kind: conda + name: libxcb + version: '1.16' + build: hb9d3cd8_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libxcb-1.16-hb9d3cd8_1.conda + sha256: 33aa5fc997468b07ab3020b142eacc5479e4e2c2169f467b20ab220f33dd08de + md5: 3601598f0db0470af28985e3e7ad0158 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc-ng >=13 + - pthread-stubs + - xorg-libxau >=1.0.11,<2.0a0 + - xorg-libxdmcp + license: MIT + license_family: MIT + size: 395570 + timestamp: 1724419104778 - kind: conda name: libxcrypt version: 4.4.36 @@ -4954,23 +5019,6 @@ packages: license_family: Other size: 56119 timestamp: 1716874608785 -- kind: conda - name: libzlib - version: 1.2.13 - build: h4ab18f5_6 - build_number: 6 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-h4ab18f5_6.conda - sha256: 8ced4afed6322172182af503f21725d072a589a6eb918f8a58135c1e00d35980 - md5: 27329162c0dc732bcf67a4e0cd488125 - depends: - - libgcc-ng >=12 - constrains: - - zlib 1.2.13 *_6 - license: Zlib - license_family: Other - size: 61571 - timestamp: 1716874066944 - kind: conda name: libzlib version: 1.2.13 @@ -5005,6 +5053,23 @@ packages: license_family: Other size: 46768 timestamp: 1716874151980 +- kind: conda + name: libzlib + version: 1.3.1 + build: h4ab18f5_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-h4ab18f5_1.conda + sha256: adf6096f98b537a11ae3729eaa642b0811478f0ea0402ca67b5108fe2cb0010d + md5: 57d7dc60e9325e3de37ff8dffd18e814 + depends: + - libgcc-ng >=12 + constrains: + - zlib 1.3.1 *_1 + license: Zlib + license_family: Other + size: 61574 + timestamp: 1716874187109 - kind: conda name: llvm-meta version: 5.0.0 @@ -5264,21 +5329,23 @@ packages: - kind: conda name: markupsafe version: 2.1.5 - build: py311h459d7ec_0 + build: py312h66e93f0_1 + build_number: 1 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py311h459d7ec_0.conda - sha256: 14912e557a6576e03f65991be89e9d289c6e301921b6ecfb4e7186ba974f453d - md5: a322b4185121935c871d201ae00ac143 - depends: - - libgcc-ng >=12 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 + url: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py312h66e93f0_1.conda + sha256: 5c88cd6e19437015de16bde30dd25791aca63ac9cbb8d66b65f365ecff1b235b + md5: 80b79ce0d3dc127e96002dfdcec0a2a5 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 constrains: - jinja2 >=3.0.0 license: BSD-3-Clause license_family: BSD - size: 27502 - timestamp: 1706900084436 + size: 26772 + timestamp: 1724959630484 - kind: conda name: markupsafe version: 2.1.5 @@ -5582,7 +5649,7 @@ packages: - libpng >=1.6.43,<1.7.0a0 - libstdcxx-ng >=12 - libtiff >=4.6.0,<4.7.0a0 - - libzlib >=1.2.13,<1.3.0a0 + - libzlib >=1.2.13,<2.0.0a0 license: BSD-2-Clause license_family: BSD size: 341592 @@ -5806,20 +5873,22 @@ packages: timestamp: 1708118184900 - kind: conda name: pcre2 - version: '10.43' - build: hcad00b1_0 + version: '10.44' + build: hba22ea6_2 + build_number: 2 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.43-hcad00b1_0.conda - sha256: 766dd986a7ed6197676c14699000bba2625fd26c8a890fcb7a810e5cf56155bc - md5: 8292dea9e022d9610a11fce5e0896ed8 + url: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.44-hba22ea6_2.conda + sha256: 1087716b399dab91cc9511d6499036ccdc53eb29a288bebcb19cf465c51d7c0d + md5: df359c09c41cd186fffb93a2d87aa6f5 depends: + - __glibc >=2.17,<3.0.a0 - bzip2 >=1.0.8,<2.0a0 - libgcc-ng >=12 - - libzlib >=1.2.13,<1.3.0a0 + - libzlib >=1.3.1,<2.0a0 license: BSD-3-Clause license_family: BSD - size: 950847 - timestamp: 1708118050286 + size: 952308 + timestamp: 1723488734144 - kind: conda name: perl version: 5.32.1 @@ -5895,30 +5964,6 @@ packages: license: HPND size: 41877756 timestamp: 1712155234508 -- kind: conda - name: pillow - version: 10.3.0 - build: py311h18e6fac_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/pillow-10.3.0-py311h18e6fac_0.conda - sha256: 6e54cc2acead8884e81e3e1b4f299b18d5daa0e3d11f4db5686db9e2ada2a353 - md5: 6c520a9d36c9d7270988c7a6c360d6d4 - depends: - - freetype >=2.12.1,<3.0a0 - - lcms2 >=2.16,<3.0a0 - - libgcc-ng >=12 - - libjpeg-turbo >=3.0.0,<4.0a0 - - libtiff >=4.6.0,<4.7.0a0 - - libwebp-base >=1.3.2,<2.0a0 - - libxcb >=1.15,<1.16.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - openjpeg >=2.5.2,<3.0a0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - tk >=8.6.13,<8.7.0a0 - license: HPND - size: 42600867 - timestamp: 1712154582003 - kind: conda name: pillow version: 10.3.0 @@ -5968,6 +6013,30 @@ packages: license: HPND size: 42541715 timestamp: 1712155039095 +- kind: conda + name: pillow + version: 10.4.0 + build: py312h287a98d_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/pillow-10.4.0-py312h287a98d_0.conda + sha256: f3bca9472702f32bf85196efbf013e9dabe130776e76c7f81062f18682f33a05 + md5: 59ea71eed98aee0bebbbdd3b118167c7 + depends: + - freetype >=2.12.1,<3.0a0 + - lcms2 >=2.16,<3.0a0 + - libgcc-ng >=12 + - libjpeg-turbo >=3.0.0,<4.0a0 + - libtiff >=4.6.0,<4.7.0a0 + - libwebp-base >=1.4.0,<2.0a0 + - libxcb >=1.16,<1.17.0a0 + - libzlib >=1.3.1,<2.0a0 + - openjpeg >=2.5.2,<3.0a0 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - tk >=8.6.13,<8.7.0a0 + license: HPND + size: 42068301 + timestamp: 1719903698022 - kind: conda name: pixman version: 0.43.2 @@ -6407,12 +6476,12 @@ packages: timestamp: 1713552154779 - kind: conda name: python - version: 3.11.9 - build: hb806964_0_cpython + version: 3.12.3 + build: hab00c5b_0_cpython subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.9-hb806964_0_cpython.conda - sha256: 177f33a1fb8d3476b38f73c37b42f01c0b014fa0e039a701fd9f83d83aae6d40 - md5: ac68acfa8b558ed406c75e98d3428d7b + url: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.3-hab00c5b_0_cpython.conda + sha256: f9865bcbff69f15fd89a33a2da12ad616e98d65ce7c83c644b92e66e5016b227 + md5: 2540b74d304f71d3e89c81209db4db84 depends: - bzip2 >=1.0.8,<2.0a0 - ld_impl_linux-64 >=2.36.1 @@ -6420,10 +6489,10 @@ packages: - libffi >=3.4,<4.0a0 - libgcc-ng >=12 - libnsl >=2.0.1,<2.1.0a0 - - libsqlite >=3.45.3,<4.0a0 + - libsqlite >=3.45.2,<4.0a0 - libuuid >=2.38.1,<3.0a0 - libxcrypt >=4.4.36 - - libzlib >=1.2.13,<1.3.0a0 + - libzlib >=1.2.13,<2.0.0a0 - ncurses >=6.4.20240210,<7.0a0 - openssl >=3.2.1,<4.0a0 - readline >=8.2,<9.0a0 @@ -6431,10 +6500,10 @@ packages: - tzdata - xz >=5.2.6,<6.0a0 constrains: - - python_abi 3.11.* *_cp311 + - python_abi 3.12.* *_cp312 license: Python-2.0 - size: 30884494 - timestamp: 1713553104915 + size: 31991381 + timestamp: 1713208036041 - kind: conda name: python-dateutil version: 2.9.0 @@ -6481,21 +6550,6 @@ packages: license_family: BSD size: 6776 timestamp: 1695147727582 -- kind: conda - name: python_abi - version: '3.11' - build: 4_cp311 - build_number: 4 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.11-4_cp311.conda - sha256: 0be3ac1bf852d64f553220c7e6457e9c047dfb7412da9d22fbaa67e60858b3cf - md5: d786502c97404c94d7d58d258a445a65 - constrains: - - python 3.11.* *_cpython - license: BSD-3-Clause - license_family: BSD - size: 6385 - timestamp: 1695147338551 - kind: conda name: python_abi version: '3.11' @@ -6511,6 +6565,21 @@ packages: license_family: BSD size: 6492 timestamp: 1695147509940 +- kind: conda + name: python_abi + version: '3.12' + build: 5_cp312 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-5_cp312.conda + sha256: d10e93d759931ffb6372b45d65ff34d95c6000c61a07e298d162a3bc2accebb0 + md5: 0424ae29b104430108f5218a66db7260 + constrains: + - python 3.12.* *_cpython + license: BSD-3-Clause + license_family: BSD + size: 6238 + timestamp: 1723823388266 - kind: conda name: pytz version: '2024.1' @@ -6526,24 +6595,6 @@ packages: license_family: MIT size: 188538 timestamp: 1706886944988 -- kind: conda - name: pyyaml - version: 6.0.1 - build: py311h459d7ec_1 - build_number: 1 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.1-py311h459d7ec_1.conda - sha256: 28729ef1ffa7f6f9dfd54345a47c7faac5d34296d66a2b9891fb147f4efe1348 - md5: 52719a74ad130de8fb5d047dc91f247a - depends: - - libgcc-ng >=12 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - yaml >=0.2.5,<0.3.0a0 - license: MIT - license_family: MIT - size: 200626 - timestamp: 1695373818537 - kind: conda name: pyyaml version: 6.0.1 @@ -6599,6 +6650,25 @@ packages: license_family: MIT size: 162428 timestamp: 1695373824922 +- kind: conda + name: pyyaml + version: 6.0.2 + build: py312h66e93f0_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0.2-py312h66e93f0_1.conda + sha256: a60705971e958724168f2ebbb8ed4853067f1d3f7059843df3903e3092bbcffa + md5: 549e5930e768548a89c23f595dac5a95 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - yaml >=0.2.5,<0.3.0a0 + license: MIT + license_family: MIT + size: 206553 + timestamp: 1725456256213 - kind: conda name: pyyaml-env-tag version: '0.1' @@ -6661,22 +6731,6 @@ packages: license_family: GPL size: 255870 timestamp: 1679532707590 -- kind: conda - name: regex - version: 2024.5.15 - build: py311h331c9d8_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/regex-2024.5.15-py311h331c9d8_0.conda - sha256: 924dc09ef5e0971f67465b3e1e092c924519b172bff2fe4a66722ed48e3d859f - md5: f789a94f81f6bec0a726cc69bd65b290 - depends: - - libgcc-ng >=12 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - license: Python-2.0 - license_family: PSF - size: 407596 - timestamp: 1715828506170 - kind: conda name: regex version: 2024.5.15 @@ -6728,6 +6782,24 @@ packages: license_family: PSF size: 313632 timestamp: 1715828647380 +- kind: conda + name: regex + version: 2024.7.24 + build: py312h66e93f0_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/regex-2024.7.24-py312h66e93f0_1.conda + sha256: 1203513e7c2d012146d7510b72802a875f6dfe8fefec378d3b42ebf4e29debff + md5: 1bf3a46297156cc38202c7e6952d28b9 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc >=13 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: Python-2.0 + license_family: PSF + size: 399200 + timestamp: 1724957225065 - kind: conda name: requests version: 2.32.2 @@ -6789,131 +6861,133 @@ packages: timestamp: 1693455923632 - kind: conda name: rust - version: 1.76.0 - build: h4ff7c5d_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/rust-1.76.0-h4ff7c5d_0.conda - sha256: dc10bd033d5f7de40c39d62a3ec084117396fd7cae6c25bb20f087b119c08bd9 - md5: 015ddfe83f6971fb9d25da68032fafc7 + version: 1.80.1 + build: h0a17960_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/rust-1.80.1-h0a17960_0.conda + sha256: 7058519747d4b81f3cab23a0d6b4326c80879d38b2a0bf11cade52fc59980b8f + md5: dba7ad0d2f707fee5e85c6a19042fdb4 depends: - - rust-std-aarch64-apple-darwin 1.76.0 hf6ec828_0 + - __glibc >=2.17,<3.0.a0 + - gcc_impl_linux-64 + - libgcc-ng >=12 + - libzlib >=1.3.1,<2.0a0 + - rust-std-x86_64-unknown-linux-gnu 1.80.1 h2c6d0dc_0 + - sysroot_linux-64 >=2.17 license: MIT license_family: MIT - size: 146506818 - timestamp: 1707422528708 + size: 198885602 + timestamp: 1723153698032 - kind: conda name: rust - version: 1.76.0 - build: h70c747d_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/rust-1.76.0-h70c747d_0.conda - sha256: 7d2e7821520862b3ac5829677de1c18a91a50621fae86122c709cc219e753040 - md5: 4ff9e2eff880011bcb18d3274aa44f96 + version: 1.80.1 + build: h4ff7c5d_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/rust-1.80.1-h4ff7c5d_0.conda + sha256: 5b296bb663be4c10bf3d07eaaa69c3c5856bd198152a775404e161f6780236bb + md5: 76d236abc95f2d77f7a3c16f1b565b3e depends: - - gcc_impl_linux-64 - - libgcc-ng >=12 - - libzlib >=1.2.13,<1.3.0a0 - - rust-std-x86_64-unknown-linux-gnu 1.76.0 h2c6d0dc_0 + - rust-std-aarch64-apple-darwin 1.80.1 hf6ec828_0 license: MIT license_family: MIT - size: 189872921 - timestamp: 1707423016244 + size: 197866703 + timestamp: 1723155024117 - kind: conda name: rust - version: 1.76.0 - build: h7e1429e_0 + version: 1.80.1 + build: h6c54e5d_0 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/rust-1.76.0-h7e1429e_0.conda - sha256: 27e7a673bbb0c3ca44459259943fbd4b4e4143e438c036feb8b39626ee3e5e17 - md5: 2573dcf36a823ece11260258ec4ed3a1 + url: https://conda.anaconda.org/conda-forge/osx-64/rust-1.80.1-h6c54e5d_0.conda + sha256: 8e799c550545a41baef23a543ffd87620cf67c0afd3494ea40b6081cbf8aabe7 + md5: ecf36b937ded5c641039161f7f5c7f64 depends: - - rust-std-x86_64-apple-darwin 1.76.0 h38e4360_0 + - rust-std-x86_64-apple-darwin 1.80.1 h38e4360_0 license: MIT license_family: MIT - size: 191502783 - timestamp: 1707422977236 + size: 202606989 + timestamp: 1723154998091 - kind: conda name: rust - version: 1.76.0 + version: 1.80.1 build: hf8d6059_0 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/rust-1.76.0-hf8d6059_0.conda - sha256: 8e0f5bcba95e618890d440c306a2a6329de85a4b271ee21a4b665b298704effb - md5: 7d4801d0134d5c42f2c83b6124b659d3 + url: https://conda.anaconda.org/conda-forge/win-64/rust-1.80.1-hf8d6059_0.conda + sha256: 3d8f926d5db03762a1e3ff723295ea18674c29960e2e501a16c9413304698654 + md5: 385a661cb1746cb6c62eb55712b412dd depends: - - rust-std-x86_64-pc-windows-msvc 1.76.0 h17fc481_0 + - rust-std-x86_64-pc-windows-msvc 1.80.1 h17fc481_0 license: MIT license_family: MIT - size: 187843360 - timestamp: 1707425717398 + size: 194534225 + timestamp: 1723155969495 - kind: conda name: rust-std-aarch64-apple-darwin - version: 1.76.0 + version: 1.80.1 build: hf6ec828_0 subdir: noarch noarch: generic - url: https://conda.anaconda.org/conda-forge/noarch/rust-std-aarch64-apple-darwin-1.76.0-hf6ec828_0.conda - sha256: a00af5f95dc65e9acf9b078e6fa24217995c525ca415f3b504849301337d4e36 - md5: c1a09b44dd7dac9be17ea3b9e59b47c3 + url: https://conda.anaconda.org/conda-forge/noarch/rust-std-aarch64-apple-darwin-1.80.1-hf6ec828_0.conda + sha256: 6cd8c3cf93fb8348c815595eced946316bc81a0bf8c6fc8f6b9f27e270734770 + md5: b3b07764d1fa59acf5c356bbb727db20 depends: - __unix constrains: - - rust >=1.76.0,<1.76.1.0a0 + - rust >=1.80.1,<1.80.2.0a0 license: MIT license_family: MIT - size: 30595488 - timestamp: 1707422444224 + size: 30991019 + timestamp: 1723152907303 - kind: conda name: rust-std-x86_64-apple-darwin - version: 1.76.0 + version: 1.80.1 build: h38e4360_0 subdir: noarch noarch: generic - url: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-apple-darwin-1.76.0-h38e4360_0.conda - sha256: ba59cc6260747203468f344ba5e55f5227cce7b7bf684216eab3b3db1387742c - md5: 0e0d3dc80e8689f9fceaa9d57cbf9ea3 + url: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-apple-darwin-1.80.1-h38e4360_0.conda + sha256: 56a30b275235975ea4e37f8d703818079601163aca92195a45468b0e7d6beffb + md5: b1ce3c6d57f2cf9f5a8b2448e3b6f499 depends: - __unix constrains: - - rust >=1.76.0,<1.76.1.0a0 + - rust >=1.80.1,<1.80.2.0a0 license: MIT license_family: MIT - size: 31508989 - timestamp: 1707422739082 + size: 31988631 + timestamp: 1723152891461 - kind: conda name: rust-std-x86_64-pc-windows-msvc - version: 1.76.0 + version: 1.80.1 build: h17fc481_0 subdir: noarch noarch: generic - url: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-pc-windows-msvc-1.76.0-h17fc481_0.conda - sha256: 7592e543e3222ae2b183e062eccf16595d434882cefbb5655baaf808b80f7231 - md5: 64bd914640f496459def58497a625321 + url: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-pc-windows-msvc-1.80.1-h17fc481_0.conda + sha256: a4f118c6211f717846c094e58d3baef32215d1a2414d51c3e08b739dce75c28f + md5: f21862b6487af2fe504ca2b78dfec822 depends: - __win constrains: - - rust >=1.76.0,<1.76.1.0a0 + - rust >=1.80.1,<1.80.2.0a0 license: MIT license_family: MIT - size: 25555117 - timestamp: 1707425386866 + size: 25255952 + timestamp: 1723155705619 - kind: conda name: rust-std-x86_64-unknown-linux-gnu - version: 1.76.0 + version: 1.80.1 build: h2c6d0dc_0 subdir: noarch noarch: generic - url: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.76.0-h2c6d0dc_0.conda - sha256: 5438720aa554fb7ce68fd544f2e35ac0a24c4efdab9cae7dd1371bf699a74ec5 - md5: b27ecce0eb266a44186b8a5b7434d59e + url: https://conda.anaconda.org/conda-forge/noarch/rust-std-x86_64-unknown-linux-gnu-1.80.1-h2c6d0dc_0.conda + sha256: 769cb83291804c9faa0de81534ceb3794cd06efd4d5164872bd5527e511f12a7 + md5: 0a5b8783d18a253b0812a5501df297af depends: - __unix constrains: - - rust >=1.76.0,<1.76.1.0a0 + - rust >=1.80.1,<1.80.2.0a0 license: MIT license_family: MIT - size: 33981347 - timestamp: 1707422883354 + size: 33938994 + timestamp: 1723153507938 - kind: conda name: setuptools version: 70.0.0 @@ -6990,20 +7064,22 @@ packages: timestamp: 1707319626819 - kind: conda name: sysroot_linux-64 - version: '2.12' - build: he073ed8_17 - build_number: 17 + version: '2.17' + build: h4a8ded7_16 + build_number: 16 subdir: noarch noarch: generic - url: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.12-he073ed8_17.conda - sha256: b4e4d685e41cb36cfb16f0cb15d2c61f8f94f56fab38987a44eff95d8a673fb5 - md5: 595db67e32b276298ff3d94d07d47fbf + url: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.17-h4a8ded7_16.conda + sha256: b892b0b9c6dc8efe8b9b5442597d1ab8d65c0dc7e4e5a80f822cbdf0a639bd77 + md5: 223fe8a3ff6d5e78484a9d58eb34d055 depends: - - kernel-headers_linux-64 2.6.32 he073ed8_17 + - _sysroot_linux-64_curr_repodata_hack 3.* + - kernel-headers_linux-64 3.10.0 h4a8ded7_16 + - tzdata license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later AND MPL-2.0 license_family: GPL - size: 15127123 - timestamp: 1708000843849 + size: 15513240 + timestamp: 1720621429816 - kind: conda name: tapi version: 1100.0.11 @@ -7106,7 +7182,7 @@ packages: md5: d453b98d9c83e71da0741bb0ff4d76bc depends: - libgcc-ng >=12 - - libzlib >=1.2.13,<1.3.0a0 + - libzlib >=1.2.13,<2.0.0a0 license: TCL license_family: BSD size: 3318875 @@ -7182,25 +7258,6 @@ packages: license_family: PROPRIETARY size: 1283972 timestamp: 1666630199266 -- kind: conda - name: ukkonen - version: 1.0.1 - build: py311h9547e67_4 - build_number: 4 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.0.1-py311h9547e67_4.conda - sha256: c2d33e998f637b594632eba3727529171a06eb09896e36aa42f1ebcb03779472 - md5: 586da7df03b68640de14dc3e8bcbf76f - depends: - - cffi - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - license: MIT - license_family: MIT - size: 13961 - timestamp: 1695549513130 - kind: conda name: ukkonen version: 1.0.1 @@ -7220,6 +7277,25 @@ packages: license_family: MIT size: 13958 timestamp: 1695549884615 +- kind: conda + name: ukkonen + version: 1.0.1 + build: py312h8572e83_4 + build_number: 4 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ukkonen-1.0.1-py312h8572e83_4.conda + sha256: f9a4384d466f4d8b5b497d951329dd4407ebe02f8f93456434e9ab789d6e23ce + md5: 52c9e25ee0a32485a102eeecdb7eef52 + depends: + - cffi + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - python >=3.12.0rc3,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: MIT + license_family: MIT + size: 14050 + timestamp: 1695549556745 - kind: conda name: ukkonen version: 1.0.1 @@ -7388,22 +7464,6 @@ packages: license_family: MIT size: 218421 timestamp: 1682376911339 -- kind: conda - name: watchdog - version: 4.0.1 - build: py311h38be061_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/watchdog-4.0.1-py311h38be061_0.conda - sha256: 212199830354d395aa123584e170d0ebc26c4cbceb51d2f5e93c795cbbd500df - md5: 1a3b92c14f3ba0b227e2e31b3398831f - depends: - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - pyyaml >=3.10 - license: Apache-2.0 - license_family: APACHE - size: 139922 - timestamp: 1716561875196 - kind: conda name: watchdog version: 4.0.1 @@ -7455,6 +7515,22 @@ packages: license_family: APACHE size: 118168 timestamp: 1716561970374 +- kind: conda + name: watchdog + version: 5.0.1 + build: py312h7900ff3_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/watchdog-5.0.1-py312h7900ff3_0.conda + sha256: a7356010dd263a82a3e2a8bb6b79d3d3f41506834b678ca7249626b51970c812 + md5: 0c36de452bacf602bca9fca222638815 + depends: + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - pyyaml >=3.10 + license: Apache-2.0 + license_family: APACHE + size: 140427 + timestamp: 1725361239347 - kind: conda name: webencodings version: 0.5.1 @@ -7535,21 +7611,22 @@ packages: - kind: conda name: xorg-libx11 version: 1.8.9 - build: h8ee46fc_0 + build: hb711507_1 + build_number: 1 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.9-h8ee46fc_0.conda - sha256: 3e53ba247f1ad68353f18aceba5bf8ce87e3dea930de85d36946844a7658c9fb - md5: 077b6e8ad6a3ddb741fce2496dd01bec + url: https://conda.anaconda.org/conda-forge/linux-64/xorg-libx11-1.8.9-hb711507_1.conda + sha256: 66eabe62b66c1597c4a755dcd3f4ce2c78adaf7b32e25dfee45504d67d7735c1 + md5: 4a6d410296d7e39f00bacdee7df046e9 depends: - libgcc-ng >=12 - - libxcb >=1.15,<1.16.0a0 + - libxcb >=1.16,<1.17.0a0 - xorg-kbproto - xorg-xextproto >=7.3.0,<8.0a0 - xorg-xproto license: MIT license_family: MIT - size: 828060 - timestamp: 1712415742569 + size: 832198 + timestamp: 1718846846409 - kind: conda name: xorg-libxau version: 1.0.11 @@ -7872,22 +7949,6 @@ packages: license_family: Other size: 107894 timestamp: 1716874644593 -- kind: conda - name: zlib - version: 1.2.13 - build: h4ab18f5_6 - build_number: 6 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-h4ab18f5_6.conda - sha256: 534824ea44939f3e59ca8ebb95e3ece6f50f9d2a0e69999fbc692311252ed6ac - md5: 559d338a4234c2ad6e676f460a093e67 - depends: - - libgcc-ng >=12 - - libzlib 1.2.13 h4ab18f5_6 - license: Zlib - license_family: Other - size: 92883 - timestamp: 1716874088980 - kind: conda name: zlib version: 1.2.13 @@ -7921,22 +7982,21 @@ packages: size: 78193 timestamp: 1716874169064 - kind: conda - name: zstandard - version: 0.19.0 - build: py311hd4cff14_0 + name: zlib + version: 1.3.1 + build: h4ab18f5_1 + build_number: 1 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.19.0-py311hd4cff14_0.tar.bz2 - sha256: 8aac43cc4fbdcc420fe8a22c764b67f6ac9168b103bfd10d79a82b748304ddf6 - md5: 056b3271f46abaa4673c8c6783283a07 + url: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.1-h4ab18f5_1.conda + sha256: cee16ab07a11303de721915f0a269e8c7a54a5c834aa52f74b1cc3a59000ade8 + md5: 9653f1bf3766164d0e65fa723cabbc54 depends: - - cffi >=1.8 - libgcc-ng >=12 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - license: BSD-3-Clause - license_family: BSD - size: 696792 - timestamp: 1667296297763 + - libzlib 1.3.1 h4ab18f5_1 + license: Zlib + license_family: Other + size: 93004 + timestamp: 1716874213487 - kind: conda name: zstandard version: 0.19.0 @@ -7989,6 +8049,27 @@ packages: license_family: BSD size: 477912 timestamp: 1667297003579 +- kind: conda + name: zstandard + version: 0.23.0 + build: py312hef9b889_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/zstandard-0.23.0-py312hef9b889_1.conda + sha256: b97015e146437283f2213ff0e95abdc8e2480150634d81fbae6b96ee09f5e50b + md5: 8b7069e9792ee4e5b4919a7a306d2e67 + depends: + - __glibc >=2.17,<3.0.a0 + - cffi >=1.11 + - libgcc >=13 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - zstd >=1.5.6,<1.5.7.0a0 + - zstd >=1.5.6,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + size: 419552 + timestamp: 1725305670210 - kind: conda name: zstd version: 1.5.6 diff --git a/pixi.toml b/pixi.toml index bdcc6646..d46b2c86 100644 --- a/pixi.toml +++ b/pixi.toml @@ -22,7 +22,7 @@ deploy-dev = "mike deploy --push dev devel" [dependencies] openssl = "3.*" -rust = ">=1.76.0,<1.77" +rust = "~=1.80.0" pre-commit = "3.3.3.*" compilers = "1.6.0.*" libssh2 = "1.11.0.*" diff --git a/rust-toolchain b/rust-toolchain index 7c7053aa..aaceec04 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.75.0 +1.80.0 diff --git a/src/build.rs b/src/build.rs index 61d63515..1417f23a 100644 --- a/src/build.rs +++ b/src/build.rs @@ -2,14 +2,17 @@ //! [`Output`] use std::{path::PathBuf, vec}; -use miette::IntoDiagnostic; +use miette::{Context, IntoDiagnostic}; use rattler_conda_types::{Channel, MatchSpec, ParseStrictness}; -use rattler_index::index; use rattler_solve::{ChannelPriority, SolveStrategy}; use crate::{ - metadata::Output, package_test, package_test::TestConfiguration, recipe::parser::TestType, - render::solver::load_repodatas, tool_configuration, + metadata::{build_reindexed_channels, Output}, + package_test, + package_test::TestConfiguration, + recipe::parser::TestType, + render::solver::load_repodatas, + tool_configuration, }; /// Check if the build should be skipped because it already exists in any of the @@ -32,7 +35,10 @@ pub async fn skip_existing( return Ok(outputs); }; - let all_channels = first_output.reindex_channels().into_diagnostic()?; + let all_channels = + build_reindexed_channels(&first_output.build_configuration, tool_configuration) + .into_diagnostic() + .context("failed to reindex output channel")?; let match_specs = outputs .iter() @@ -109,12 +115,6 @@ pub async fn run_build( let directories = output.build_configuration.directories.clone(); - index( - &directories.output_dir, - Some(&output.build_configuration.target_platform.clone()), - ) - .into_diagnostic()?; - let output = output .fetch_sources(tool_configuration) .await @@ -127,6 +127,11 @@ pub async fn run_build( .await .into_diagnostic()?; + output + .install_environments(tool_configuration) + .await + .into_diagnostic()?; + output.run_build_script().await.into_diagnostic()?; // Package all the new files @@ -164,7 +169,10 @@ pub async fn run_build( test_prefix: directories.work_dir.join("test"), target_platform: Some(output.build_configuration.host_platform), keep_test_prefix: tool_configuration.no_clean, - channels: output.reindex_channels().into_diagnostic()?, + //channels: output.reindex_channels().into_diagnostic()?, + channels: build_reindexed_channels(&output.build_configuration, tool_configuration) + .into_diagnostic() + .context("failed to reindex output channel")?, channel_priority: ChannelPriority::Strict, solve_strategy: SolveStrategy::Highest, tool_configuration: tool_configuration.clone(), diff --git a/src/cache.rs b/src/cache.rs index 20b1ab86..2291285e 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -1,18 +1,19 @@ //! Functions to deal with the build cache +use std::{ + collections::{BTreeMap, HashSet}, + path::{Path, PathBuf}, +}; + use fs_err as fs; use memchr::memmem; use memmap2::Mmap; -use miette::IntoDiagnostic; +use miette::{Context, IntoDiagnostic}; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; -use std::{ - collections::{BTreeMap, HashSet}, - path::{Path, PathBuf}, -}; use crate::{ env_vars, - metadata::Output, + metadata::{build_reindexed_channels, Output}, packaging::{contains_prefix_binary, contains_prefix_text, content_type, Files}, recipe::parser::{Dependency, Requirements}, render::resolved_dependencies::{resolve_dependencies, FinalizedDependencies}, @@ -22,7 +23,8 @@ use crate::{ /// Error type for cache key generation #[derive(Debug, thiserror::Error)] pub enum CacheKeyError { - /// No cache key available (when no `cache` section is present in the recipe) + /// No cache key available (when no `cache` section is present in the + /// recipe) #[error("No cache key available")] NoCacheKeyAvailable, /// Error serializing cache key with serde_json @@ -39,16 +41,17 @@ pub struct Cache { pub finalized_dependencies: FinalizedDependencies, /// The prefix files that are included in the cache pub prefix_files: Vec<(PathBuf, bool)>, - /// The prefix that was used at build time (needs to be replaced when restoring the files) + /// The prefix that was used at build time (needs to be replaced when + /// restoring the files) pub prefix: PathBuf, } impl Output { - /// Compute a cache key that contains all the information that was used to build the cache, - /// including the relevant variant information. + /// Compute a cache key that contains all the information that was used to + /// build the cache, including the relevant variant information. pub fn cache_key(&self) -> Result { - // we have a variant, and we need to find the used variables that are used in the cache to create a - // hash for the cache ... + // we have a variant, and we need to find the used variables that are used in + // the cache to create a hash for the cache ... if let Some(cache) = &self.recipe.cache { // we need to apply the variant to the cache requirements though let requirement_names = cache @@ -74,8 +77,9 @@ impl Output { } } // always insert the target platform and build platform - // we are using the `host_platform` here because for the cache it should not matter whether it's being - // build for `noarch` or not (one can have mixed outputs, in fact). + // we are using the `host_platform` here because for the cache it should not + // matter whether it's being build for `noarch` or not (one can have + // mixed outputs, in fact). selected_variant.insert("host_platform", self.host_platform().to_string()); selected_variant.insert( "build_platform", @@ -113,8 +117,8 @@ impl Output { let source = &cache_dir.join("prefix").join(file); copy_file(source, &dest, &mut paths_created, ©_options).into_diagnostic()?; - // check if the symlink starts with the old prefix, and if yes, make the symlink absolute - // with the new prefix + // check if the symlink starts with the old prefix, and if yes, make the symlink + // absolute with the new prefix if source.is_symlink() { let symlink_target = fs::read_link(source).into_diagnostic()?; if let Ok(rest) = symlink_target.strip_prefix(&cache_prefix) { @@ -139,7 +143,8 @@ impl Output { &self, tool_configuration: &crate::tool_configuration::Configuration, ) -> Result { - // if we don't have a cache, we need to run the cache build with our current workdir, and then return the cache + // if we don't have a cache, we need to run the cache build with our current + // workdir, and then return the cache let span = tracing::info_span!("Running cache build"); let _enter = span.enter(); @@ -163,7 +168,10 @@ impl Output { return self.restore_cache(cache_dir).await; } - let channels = self.reindex_channels().unwrap(); + // Reindex the channels + let channels = build_reindexed_channels(&self.build_configuration, tool_configuration) + .into_diagnostic() + .context("failed to reindex output channel")?; let finalized_dependencies = resolve_dependencies(&cache.requirements, self, &channels, tool_configuration) @@ -247,8 +255,9 @@ impl Output { } } -/// Simple replace prefix function that does a direct replacement without any padding considerations -/// because we know that the prefix is the same length as the original prefix. +/// Simple replace prefix function that does a direct replacement without any +/// padding considerations because we know that the prefix is the same length as +/// the original prefix. fn replace_prefix(file: &Path, old_prefix: &Path, new_prefix: &Path) -> Result<(), miette::Error> { // mmap the file, and use the fast string search to find the prefix let output = { diff --git a/src/console_utils.rs b/src/console_utils.rs index 49272dc2..ca9bb688 100644 --- a/src/console_utils.rs +++ b/src/console_utils.rs @@ -1,21 +1,21 @@ //! This module contains utilities for logging and progress bar handling. -use clap_verbosity_flag::{InfoLevel, Verbosity}; -use console::style; -use indicatif::{ - HumanBytes, HumanDuration, MultiProgress, ProgressBar, ProgressState, ProgressStyle, -}; -use std::borrow::Cow; -use std::time::Duration; use std::{ + borrow::Cow, collections::HashMap, + future::Future, io, str::FromStr, sync::{Arc, Mutex}, - time::Instant, + time::{Duration, Instant}, +}; + +use clap_verbosity_flag::{InfoLevel, Verbosity}; +use console::style; +use indicatif::{ + HumanBytes, HumanDuration, MultiProgress, ProgressBar, ProgressState, ProgressStyle, }; use tracing::{field, Level}; use tracing_core::{span::Id, Event, Field, Subscriber}; -use tracing_subscriber::util::SubscriberInitExt; use tracing_subscriber::{ filter::{Directive, ParseError}, fmt::{ @@ -25,6 +25,7 @@ use tracing_subscriber::{ }, layer::{Context, SubscriberExt}, registry::LookupSpan, + util::SubscriberInitExt, EnvFilter, Layer, }; @@ -297,7 +298,8 @@ impl LoggingOutputHandler { } } - /// Return a string with the current indentation level (bars added to the front of the string). + /// Return a string with the current indentation level (bars added to the + /// front of the string). pub fn with_indent_levels(&self, template: &str) -> String { let state = self.state.lock().unwrap(); let indent_str = indent_levels(state.indentation_level); @@ -309,7 +311,8 @@ impl LoggingOutputHandler { &self.progress_bars } - /// Returns the style to use for a progressbar that is currently in progress. + /// Returns the style to use for a progressbar that is currently in + /// progress. pub fn default_bytes_style(&self) -> indicatif::ProgressStyle { let template_str = self.with_indent_levels( "{spinner:.green} {prefix:20!} [{elapsed_precise}] [{bar:40!.bright.yellow/dim.white}] {bytes:>8} @ {smoothed_bytes_per_sec:8}" @@ -340,7 +343,8 @@ impl LoggingOutputHandler { ) } - /// Returns the style to use for a progressbar that is currently in progress. + /// Returns the style to use for a progressbar that is currently in + /// progress. pub fn default_progress_style(&self) -> indicatif::ProgressStyle { let template_str = self.with_indent_levels( "{spinner:.green} {prefix:20!} [{elapsed_precise}] [{bar:40!.bright.yellow/dim.white}] {pos:>7}/{len:7}" @@ -351,7 +355,8 @@ impl LoggingOutputHandler { .progress_chars("━━╾─") } - /// Returns the style to use for a progressbar that is in Deserializing state. + /// Returns the style to use for a progressbar that is in Deserializing + /// state. pub fn deserializing_progress_style(&self) -> indicatif::ProgressStyle { let template_str = self.with_indent_levels("{spinner:.green} {prefix:20!} [{elapsed_precise}] {wide_msg}"); @@ -387,7 +392,8 @@ impl LoggingOutputHandler { .progress_chars("━━╾─") } - /// Returns the style to use for a progressbar that is indeterminate and simply shows a spinner. + /// Returns the style to use for a progressbar that is indeterminate and + /// simply shows a spinner. pub fn long_running_progress_style(&self) -> indicatif::ProgressStyle { let template_str = self.with_indent_levels("{spinner:.green} {msg}"); ProgressStyle::with_template(&template_str).unwrap() @@ -407,21 +413,56 @@ impl LoggingOutputHandler { }); } - /// Displays a spinner with the given message while running the specified function to completion. + /// Displays a spinner with the given message while running the specified + /// function to completion. pub fn wrap_in_progress T>( &self, msg: impl Into>, func: F, ) -> T { let pb = self.add_progress_bar( - ProgressBar::new_spinner().with_style(self.long_running_progress_style()), + ProgressBar::hidden() + .with_style(self.long_running_progress_style()) + .with_message(msg), ); pb.enable_steady_tick(Duration::from_millis(100)); - pb.set_message(msg); let result = func(); pb.finish_and_clear(); result } + + /// Displays a spinner with the given message while running the specified + /// function to completion. + pub async fn wrap_in_progress_async>( + &self, + msg: impl Into>, + future: Fut, + ) -> T { + self.wrap_in_progress_async_with_progress(msg, |_pb| future) + .await + } + + /// Displays a spinner with the given message while running the specified + /// function to completion. + pub async fn wrap_in_progress_async_with_progress< + T, + Fut: Future, + F: FnOnce(ProgressBar) -> Fut, + >( + &self, + msg: impl Into>, + f: F, + ) -> T { + let pb = self.add_progress_bar( + ProgressBar::hidden() + .with_style(self.long_running_progress_style()) + .with_message(msg), + ); + pb.enable_steady_tick(Duration::from_millis(100)); + let result = f(pb.clone()).await; + pb.finish_and_clear(); + result + } } impl io::Write for LoggingOutputHandler { @@ -456,7 +497,8 @@ pub enum LogStyle { Plain, } -/// Constructs a default [`EnvFilter`] that is used when the user did not specify a custom RUST_LOG. +/// Constructs a default [`EnvFilter`] that is used when the user did not +/// specify a custom RUST_LOG. pub fn get_default_env_filter( verbose: clap_verbosity_flag::LevelFilter, ) -> Result { diff --git a/src/lib.rs b/src/lib.rs index ecf76bba..41e5711a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,11 +51,11 @@ use hash::HashInfo; use metadata::{ BuildConfiguration, BuildSummary, Directories, Output, PackageIdentifier, PackagingSettings, }; -use miette::{IntoDiagnostic, WrapErr}; +use miette::IntoDiagnostic; use opt::*; use package_test::TestConfiguration; use petgraph::{algo::toposort, graph::DiGraph, visit::DfsPostOrder}; -use rattler_conda_types::{package::ArchiveType, Channel, ChannelConfig, Platform}; +use rattler_conda_types::{package::ArchiveType, Channel, Platform}; use rattler_solve::{ChannelPriority, SolveStrategy}; use recipe::{ parser::{find_outputs_from_src, Dependency, Recipe}, @@ -119,17 +119,16 @@ pub fn get_tool_config( tool_configuration::reqwest_client_from_auth_storage(args.common.auth_file.clone()) .into_diagnostic()?; - Ok(Configuration { - client, - fancy_log_handler: fancy_log_handler.clone(), - no_clean: args.keep_build, - no_test: args.no_test, - use_zstd: args.common.use_zstd, - use_bz2: args.common.use_bz2, - render_only: args.render_only, - skip_existing: args.skip_existing, - ..Configuration::default() - }) + Ok(Configuration::builder() + .with_logging_output_handler(fancy_log_handler.clone()) + .with_keep_build(args.keep_build) + .with_compression_threads(args.compression_threads) + .with_reqwest_client(client) + .with_testing(!args.no_test) + .with_zstd_repodata_enabled(args.common.use_zstd) + .with_bz2_repodata_enabled(args.common.use_zstd) + .with_skip_existing(args.skip_existing) + .finish()) } /// Returns the output for the build. @@ -331,14 +330,6 @@ pub async fn get_build_output( ), }; - if args.render_only && args.with_solve { - let output_with_resolved_dependencies = output - .resolve_dependencies(tool_config) - .await - .into_diagnostic()?; - outputs.push(output_with_resolved_dependencies); - continue; - } outputs.push(output); } @@ -385,20 +376,24 @@ pub async fn run_test_from_args( fancy_log_handler: LoggingOutputHandler, ) -> miette::Result<()> { let package_file = canonicalize(args.package_file).into_diagnostic()?; - let client = tool_configuration::reqwest_client_from_auth_storage(args.common.auth_file) - .into_diagnostic()?; - let channel_config = ChannelConfig::default_with_root_dir( - std::env::current_dir() - .into_diagnostic() - .context("failed to determine the current directory")?, - ); + let tool_config = Configuration::builder() + .with_logging_output_handler(fancy_log_handler) + .with_keep_build(true) + .with_compression_threads(args.compression_threads) + .with_reqwest_client( + tool_configuration::reqwest_client_from_auth_storage(args.common.auth_file) + .into_diagnostic()?, + ) + .with_zstd_repodata_enabled(args.common.use_zstd) + .with_bz2_repodata_enabled(args.common.use_zstd) + .finish(); let channels = args .channel .unwrap_or_else(|| vec!["conda-forge".to_string()]) .into_iter() - .map(|name| Channel::from_str(name, &channel_config).map(|c| c.base_url)) + .map(|name| Channel::from_str(name, &tool_config.channel_config).map(|c| c.base_url)) .collect::, _>>() .into_diagnostic()?; @@ -411,14 +406,7 @@ pub async fn run_test_from_args( channels, channel_priority: ChannelPriority::Strict, solve_strategy: SolveStrategy::Highest, - tool_configuration: Configuration { - client, - fancy_log_handler, - // duplicate from `keep_test_prefix`? - no_clean: false, - compression_threads: args.compression_threads, - ..Configuration::default() - }, + tool_configuration: tool_config, }; let package_name = package_file @@ -471,19 +459,18 @@ pub async fn rebuild_from_args( output.build_configuration.directories.output_dir = canonicalize(output_dir).into_diagnostic()?; - let client = tool_configuration::reqwest_client_from_auth_storage(args.common.auth_file) - .into_diagnostic()?; - - let tool_config = tool_configuration::Configuration { - client, - fancy_log_handler, - no_clean: true, - no_test: args.no_test, - use_zstd: args.common.use_zstd, - use_bz2: args.common.use_bz2, - compression_threads: args.compression_threads, - ..Configuration::default() - }; + let tool_config = Configuration::builder() + .with_logging_output_handler(fancy_log_handler) + .with_keep_build(true) + .with_compression_threads(args.compression_threads) + .with_reqwest_client( + tool_configuration::reqwest_client_from_auth_storage(args.common.auth_file) + .into_diagnostic()?, + ) + .with_testing(!args.no_test) + .with_zstd_repodata_enabled(args.common.use_zstd) + .with_bz2_repodata_enabled(args.common.use_zstd) + .finish(); output .build_configuration diff --git a/src/main.rs b/src/main.rs index faf10a43..84809f43 100644 --- a/src/main.rs +++ b/src/main.rs @@ -109,6 +109,21 @@ async fn main() -> miette::Result<()> { } if build_args.render_only { + let outputs = if build_args.with_solve { + let mut updated_outputs = Vec::new(); + for output in outputs { + updated_outputs.push( + output + .resolve_dependencies(&tool_config) + .await + .into_diagnostic()?, + ); + } + updated_outputs + } else { + outputs + }; + println!( "{}", serde_json::to_string_pretty(&outputs).into_diagnostic()? diff --git a/src/metadata.rs b/src/metadata.rs index f2f084c8..914a8094 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -20,6 +20,7 @@ use rattler_conda_types::{ }; use rattler_index::index; use rattler_package_streaming::write::CompressionLevel; +use rattler_repodata_gateway::SubdirSelection; use rattler_solve::{ChannelPriority, SolveStrategy}; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -31,6 +32,7 @@ use crate::{ recipe::parser::{Recipe, Source}, render::resolved_dependencies::FinalizedDependencies, system_tools::SystemTools, + tool_configuration, utils::remove_dir_all_force, }; /// A Git revision @@ -360,17 +362,6 @@ impl Output { .resolve(&self.build_configuration.hash, self.recipe.build().number) } - /// The channels to use when resolving dependencies - pub fn reindex_channels(&self) -> Result, std::io::Error> { - let output_dir = &self.build_configuration.directories.output_dir; - - index(output_dir, Some(&self.build_configuration.target_platform))?; - - Ok(iter::once(Channel::from_directory(output_dir).base_url) - .chain(self.build_configuration.channels.iter().cloned()) - .collect()) - } - /// retrieve an identifier for this output ({name}-{version}-{build_string}) pub fn identifier(&self) -> String { format!( @@ -630,6 +621,33 @@ impl Display for Output { } } +/// Builds the channel list and reindexes the output channel. +pub fn build_reindexed_channels( + build_configuration: &BuildConfiguration, + tool_configuration: &tool_configuration::Configuration, +) -> Result, std::io::Error> { + let output_dir = &build_configuration.directories.output_dir; + let output_channel = Channel::from_directory(output_dir); + + // Clear the repodata gateway of any cached values for the output channel. + tool_configuration.repodata_gateway.clear_repodata_cache( + &output_channel, + SubdirSelection::Some( + [build_configuration.target_platform] + .iter() + .map(ToString::to_string) + .collect(), + ), + ); + + // Reindex the output channel from the files on disk + index(output_dir, Some(&build_configuration.target_platform))?; + + Ok(iter::once(output_channel.base_url) + .chain(build_configuration.channels.iter().cloned()) + .collect()) +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/opt.rs b/src/opt.rs index 9b339d68..1d568584 100644 --- a/src/opt.rs +++ b/src/opt.rs @@ -2,15 +2,7 @@ use std::{error::Error, path::PathBuf, str::FromStr}; -#[cfg(feature = "recipe-generation")] -use crate::recipe_generator::GenerateRecipeOpts; - -use crate::{ - console_utils::{Color, LogStyle}, - tool_configuration::SkipExisting, -}; -use clap::builder::ArgPredicate; -use clap::{arg, crate_version, Parser, ValueEnum}; +use clap::{arg, builder::ArgPredicate, crate_version, Parser, ValueEnum}; use clap_complete::{shells, Generator}; use clap_complete_nushell::Nushell; use clap_verbosity_flag::{InfoLevel, Verbosity}; @@ -19,6 +11,13 @@ use rattler_package_streaming::write::CompressionLevel; use serde_json::{json, Value}; use url::Url; +#[cfg(feature = "recipe-generation")] +use crate::recipe_generator::GenerateRecipeOpts; +use crate::{ + console_utils::{Color, LogStyle}, + tool_configuration::SkipExisting, +}; + /// Application subcommands. #[derive(Parser)] #[allow(clippy::large_enum_variant)] @@ -28,16 +27,18 @@ pub enum SubCommands { /// Run a test for a single package /// - /// This creates a temporary directory, copies the package file into it, and then runs the - /// indexing. It then creates a test environment that installs the package and any extra dependencies - /// specified in the package test dependencies file. + /// This creates a temporary directory, copies the package file into it, and + /// then runs the indexing. It then creates a test environment that + /// installs the package and any extra dependencies specified in the + /// package test dependencies file. /// /// With the activated test environment, the packaged test files are run: /// /// * `info/test/run_test.sh` or `info/test/run_test.bat` on Windows /// * `info/test/run_test.py` /// - /// These test files are written at "package creation time" and are part of the package. + /// These test files are written at "package creation time" and are part of + /// the package. Test(TestOpts), /// Rebuild a package from a package file instead of a recipe. @@ -246,7 +247,8 @@ impl FromStr for PackageFormatAndCompression { /// Build options. #[derive(Parser, Clone)] pub struct BuildOpts { - /// The recipe file or directory containing `recipe.yaml`. Defaults to the current directory. + /// The recipe file or directory containing `recipe.yaml`. Defaults to the + /// current directory. #[arg( short, long, @@ -263,7 +265,8 @@ pub struct BuildOpts { #[arg(long)] pub up_to: Option, - /// The build platform to use for the build (e.g. for building with emulation, or rendering). + /// The build platform to use for the build (e.g. for building with + /// emulation, or rendering). #[arg(long, default_value_t = Platform::current())] pub build_platform: Platform, @@ -299,8 +302,10 @@ pub struct BuildOpts { #[arg(long)] pub no_build_id: bool, - /// The package format to use for the build. Can be one of `tar-bz2` or `conda`. - /// You can also add a compression level to the package format, e.g. `tar-bz2:` (from 1 to 9) or `conda:` (from -7 to 22). + /// The package format to use for the build. Can be one of `tar-bz2` or + /// `conda`. You can also add a compression level to the package format, + /// e.g. `tar-bz2:` (from 1 to 9) or `conda:` (from -7 to + /// 22). #[arg( long, default_value = "conda", @@ -310,7 +315,8 @@ pub struct BuildOpts { pub package_format: PackageFormatAndCompression, #[arg(long)] - /// The number of threads to use for compression (only relevant when also using `--package-format conda`) + /// The number of threads to use for compression (only relevant when also + /// using `--package-format conda`) pub compression_threads: Option, /// Don't store the recipe in the final package @@ -335,9 +341,11 @@ pub struct BuildOpts { /// Whether to skip packages that already exist in any channel /// If set to `none`, do not skip any packages, default when not specified. - /// If set to `local`, only skip packages that already exist locally, default when using `--skip-existing. - /// If set to `all`, skip packages that already exist in any channel. - #[arg(long, default_missing_value = "local", default_value = "none", num_args = 0..=1, help_heading = "Modifying result")] + /// If set to `local`, only skip packages that already exist locally, + /// default when using `--skip-existing. If set to `all`, skip packages + /// that already exist in any channel. + #[arg(long, default_missing_value = "local", default_value = "none", num_args = 0..=1, help_heading = "Modifying result" + )] pub skip_existing: SkipExisting, /// Extra metadata to include in about.json @@ -444,7 +452,8 @@ pub struct QuetzOpts { #[arg(short, long, env = "QUETZ_CHANNEL")] pub channel: String, - /// The Quetz API key, if none is provided, the token is read from the keychain / auth-file + /// The Quetz API key, if none is provided, the token is read from the + /// keychain / auth-file #[arg(short, long, env = "QUETZ_API_KEY")] pub api_key: Option, } @@ -474,7 +483,8 @@ pub struct ArtifactoryOpts { /// Authentication is used from the keychain / auth-file #[derive(Clone, Debug, PartialEq, Parser)] pub struct PrefixOpts { - /// The URL to the prefix.dev server (only necessary for self-hosted instances) + /// The URL to the prefix.dev server (only necessary for self-hosted + /// instances) #[arg( short, long, @@ -487,7 +497,8 @@ pub struct PrefixOpts { #[arg(short, long, env = "PREFIX_CHANNEL")] pub channel: String, - /// The prefix.dev API key, if none is provided, the token is read from the keychain / auth-file + /// The prefix.dev API key, if none is provided, the token is read from the + /// keychain / auth-file #[arg(short, long, env = "PREFIX_API_KEY")] pub api_key: Option, } @@ -503,7 +514,8 @@ pub struct AnacondaOpts { #[arg(short, long, env = "ANACONDA_CHANNEL", default_value = "main")] pub channel: Vec, - /// The Anaconda API key, if none is provided, the token is read from the keychain / auth-file + /// The Anaconda API key, if none is provided, the token is read from the + /// keychain / auth-file #[arg(short, long, env = "ANACONDA_API_KEY")] pub api_key: Option, @@ -571,10 +583,12 @@ pub struct CondaForgeOpts { #[cfg(test)] mod test { - use super::PackageFormatAndCompression; + use std::str::FromStr; + use rattler_conda_types::package::ArchiveType; use rattler_package_streaming::write::CompressionLevel; - use std::str::FromStr; + + use super::PackageFormatAndCompression; #[test] fn test_parse_packaging() { diff --git a/src/package_test/run_test.rs b/src/package_test/run_test.rs index 24abe0f5..121e24d1 100644 --- a/src/package_test/run_test.rs +++ b/src/package_test/run_test.rs @@ -177,7 +177,7 @@ async fn legacy_tests_from_folder(pkg: &Path) -> Result<(PathBuf, Vec), s } /// The configuration for a test -#[derive(Default, Clone)] +#[derive(Clone)] pub struct TestConfiguration { /// The test prefix directory (will be created) pub test_prefix: PathBuf, @@ -357,6 +357,7 @@ pub async fn run_test( dependencies.push(match_spec); create_environment( + "test", &dependencies, &platform, &prefix, @@ -446,6 +447,7 @@ impl PythonTest { } create_environment( + "test", &dependencies, &Platform::current(), prefix, @@ -525,6 +527,7 @@ impl CommandsTest { .collect::, _>>()?; create_environment( + "test", &build_dependencies, &platform, &build_prefix, @@ -556,6 +559,7 @@ impl CommandsTest { let run_env = prefix.join("run"); create_environment( + "test", &dependencies, &platform, &run_env, @@ -615,19 +619,16 @@ impl DownstreamTest { ParseStrictness::Lenient, )?, ]; - let render_only_tool_config = tool_configuration::Configuration { - render_only: true, - ..config.tool_configuration.clone() - }; let target_platform = config.target_platform.unwrap_or_else(Platform::current); let resolved = create_environment( + "test", &match_specs, &target_platform, prefix, &config.channels, - &render_only_tool_config, + &config.tool_configuration, config.channel_priority, config.solve_strategy, ) diff --git a/src/packaging/file_mapper.rs b/src/packaging/file_mapper.rs index dab4eec8..b33015cc 100644 --- a/src/packaging/file_mapper.rs +++ b/src/packaging/file_mapper.rs @@ -87,7 +87,7 @@ impl Output { /// /// * For `noarch: python` packages, the "lib/pythonX.X" prefix is stripped so that only /// the "site-packages" part is kept. Additionally, any `__pycache__` directories or - /// `.pyc` files are skipped. + /// `.pyc` files are skipped. /// * For `noarch: python` packages, furthermore `bin` is replaced with `python-scripts`, and /// `Scripts` is replaced with `python-scripts` (on Windows only). All other files are included /// as-is. diff --git a/src/post_process/relink.rs b/src/post_process/relink.rs index aa84fa3f..3a35fb79 100644 --- a/src/post_process/relink.rs +++ b/src/post_process/relink.rs @@ -76,6 +76,7 @@ pub trait Relinker { Self: Sized; /// Returns the shared libraries. + #[allow(dead_code)] fn libraries(&self) -> HashSet; /// Find libraries in the shared library and resolve them by taking into account the rpaths. diff --git a/src/recipe/parser/build.rs b/src/recipe/parser/build.rs index 8de160de..c7ae9c89 100644 --- a/src/recipe/parser/build.rs +++ b/src/recipe/parser/build.rs @@ -638,7 +638,7 @@ impl ForceFileType { } } -/// +/// Configuration related to prefix replacement #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct PrefixDetection { /// Options to force if a file is detected as text or binary diff --git a/src/recipe/parser/source.rs b/src/recipe/parser/source.rs index fb2ad5b9..7f799d6e 100644 --- a/src/recipe/parser/source.rs +++ b/src/recipe/parser/source.rs @@ -1,10 +1,10 @@ //! Parse the source section of a recipe -use std::{fmt, path::PathBuf, str::FromStr}; - use rattler_digest::{serde::SerializableHash, Md5, Md5Hash, Sha256, Sha256Hash}; use serde::{Deserialize, Serialize}; use serde_with::{formats::PreferOne, serde_as, OneOrMany}; +use std::fmt::Display; +use std::{fmt, path::PathBuf, str::FromStr}; use url::Url; use crate::{ @@ -116,13 +116,13 @@ impl GitRev { } } -impl ToString for GitRev { - fn to_string(&self) -> String { +impl Display for GitRev { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::Branch(branch) => format!("refs/heads/{}", branch), - Self::Tag(tag) => format!("refs/tags/{}", tag), - Self::Head => "HEAD".into(), - Self::Commit(commit) => commit.clone(), + Self::Branch(branch) => write!(f, "refs/heads/{}", branch), + Self::Tag(tag) => write!(f, "refs/tags/{}", tag), + Self::Head => write!(f, "HEAD"), + Self::Commit(commit) => write!(f, "{}", commit), } } } diff --git a/src/render/mod.rs b/src/render/mod.rs index a3760163..5829bda7 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -1,6 +1,7 @@ #![allow(missing_docs)] //! Render the dependencies to a final recipe +mod package_cache_reporter; pub mod pin; pub mod resolved_dependencies; mod run_exports; diff --git a/src/render/package_cache_reporter.rs b/src/render/package_cache_reporter.rs new file mode 100644 index 00000000..43d08b7a --- /dev/null +++ b/src/render/package_cache_reporter.rs @@ -0,0 +1,467 @@ +use std::{ + borrow::Cow, + collections::HashMap, + sync::{Arc, Mutex}, + time::Duration, +}; + +use indicatif::{MultiProgress, ProgressBar, ProgressFinish, ProgressStyle}; +use rattler::install::Placement; +use rattler_cache::package_cache::CacheReporter; +use rattler_conda_types::RepoDataRecord; + +/// A reporter that makes it easy to show the progress of updating the package +/// cache. +pub struct PackageCacheReporter { + inner: Arc>, +} + +impl PackageCacheReporter { + /// Construct a new reporter. + pub fn new(multi_progress: MultiProgress, placement: Placement) -> Self { + Self { + inner: Arc::new(Mutex::new(PackageCacheReporterInner { + multi_progress, + placement, + + progress_chars: Cow::Borrowed("━━╾─"), + prefix: Cow::Borrowed(""), + + validation_pb: None, + download_pb: None, + packages: Vec::new(), + + style_cache: HashMap::default(), + })), + } + } + + /// Specify a prefix for the progress bars. + pub fn with_prefix(self, prefix: impl Into>) -> Self { + let mut inner = self.inner.lock().unwrap(); + inner.prefix = prefix.into(); + inner.rerender(); + drop(inner); + self + } + + /// Adds a new package to the reporter. Returns a + /// `PackageCacheReporterEntry` which can be passed to any of the cache + /// functions of a package cache to track progress. + pub fn add(&mut self, record: &RepoDataRecord) -> PackageCacheReporterEntry { + let mut inner = self.inner.lock().unwrap(); + + let entry = ProgressEntry { + name: record.package_record.name.as_normalized().to_string(), + size: record.package_record.size, + validate_started: false, + validate_completed: false, + download_started: false, + download_progress: None, + download_completed: false, + }; + + let entry_idx = inner.packages.len(); + inner.packages.push(entry); + + drop(inner); + + PackageCacheReporterEntry { + inner: self.inner.clone(), + entry_idx, + } + } +} + +#[derive(Default)] +struct PackageCacheReporterInner { + multi_progress: MultiProgress, + placement: Placement, + + prefix: Cow<'static, str>, + progress_chars: Cow<'static, str>, + + validation_pb: Option, + download_pb: Option, + + packages: Vec, + + style_cache: HashMap, +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +struct ProgressStyleProperties { + status: ProgressStatus, + progress_type: ProgressType, +} + +/// Defines the current status of a progress bar. +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +enum ProgressStatus { + /// The progress bar is showing active work. + Active, + + /// The progress bar was active but has been paused for the moment. + Paused, + + /// The progress bar finished. + Finished, +} + +/// Defines the type of progress-bar. +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +enum ProgressType { + Generic, + Bytes, +} + +impl PackageCacheReporterInner { + fn on_validate_start(&mut self, entry_idx: usize) { + self.packages[entry_idx].validate_started = true; + self.rerender(); + } + + fn on_validate_complete(&mut self, entry_idx: usize) { + self.packages[entry_idx].validate_completed = true; + self.rerender(); + } + + fn on_download_start(&mut self, entry_idx: usize) { + self.packages[entry_idx].download_started = true; + self.rerender(); + } + + fn on_download_progress(&mut self, entry_idx: usize, progress: u64, total: Option) { + let entry = &mut self.packages[entry_idx]; + entry.download_progress = Some(progress); + entry.size = entry.size.or(total); + self.rerender(); + } + + fn on_download_completed(&mut self, entry_idx: usize) { + self.packages[entry_idx].download_completed = true; + self.rerender(); + } + + fn style(&mut self, props: ProgressStyleProperties) -> ProgressStyle { + if let Some(style) = self.style_cache.get(&props) { + return style.clone(); + } + + let style = self.build_style(&props); + self.style_cache.insert(props, style.clone()); + style + } + + fn build_style(&self, props: &ProgressStyleProperties) -> ProgressStyle { + let mut result = self.prefix.to_string(); + + // Add a spinner + match props.status { + ProgressStatus::Paused => result.push_str("{spinner:.dim} "), + ProgressStatus::Active => result.push_str("{spinner:.green} "), + ProgressStatus::Finished => result.push_str(&format!( + "{} ", + console::style(console::Emoji("✔", " ")).green() + )), + } + + // Add a prefix + result.push_str("{prefix:20!} "); + + // Add progress indicator + if props.status != ProgressStatus::Finished { + if props.status == ProgressStatus::Active { + result.push_str("[{elapsed_precise}] [{bar:20!.bright.yellow/dim.white}] "); + } else { + result.push_str("[{elapsed_precise}] [{bar:20!.dim.yellow/dim.white}] "); + } + match props.progress_type { + ProgressType::Generic => { + // Don't show position and total, because these are visible + // through text anyway. + } + ProgressType::Bytes => result.push_str("{bytes:>8} / {total_bytes:<8} "), + } + } else { + result.push_str(&format!("{}", console::style("done").green())) + } + + // Add message + result.push_str("{msg:.dim}"); + + indicatif::ProgressStyle::with_template(&result) + .expect("failed to create default style") + .progress_chars(&self.progress_chars) + } + + fn rerender(&mut self) { + self.rerender_validation(); + self.rerender_download(); + } + + fn rerender_validation(&mut self) { + // Find activate validation entries + let validating_packages: Vec<_> = self + .packages + .iter() + .filter(|e| e.validate_started) + .collect(); + if validating_packages.is_empty() && self.validation_pb.is_none() { + // If there are no packages to validate, we don't need to do anything. + return; + } + + // The total length of the progress bar + let total = validating_packages + .iter() + .map(|r| r.size.unwrap_or(1)) + .sum::(); + + // The number of packages that finish validation. + let position: u64 = validating_packages + .iter() + .filter(|r| r.validate_completed) + .map(|r| r.size.unwrap_or(1)) + .sum(); + + // True if all packages have completed validation or have started downloading. + let completed = self + .packages + .iter() + .all(|r| r.validate_completed || r.download_started); + let pending = self + .packages + .iter() + .all(|r| !r.validate_started || r.validate_completed); + + let remaining: Vec<_> = validating_packages + .into_iter() + .filter(|r| !r.validate_completed) + .collect(); + let msg = if remaining.is_empty() { + String::new() + } else { + format_progress_message(remaining) + }; + + let style = self.style(ProgressStyleProperties { + status: if completed { + ProgressStatus::Finished + } else if pending { + ProgressStatus::Paused + } else { + ProgressStatus::Active + }, + progress_type: ProgressType::Generic, + }); + + // Make sure there is a progress bar. + match &self.validation_pb { + Some(pb) => { + pb.set_style(style); + pb.set_length(total); + pb.set_position(position); + pb.set_message(msg) + } + None => { + let pb = ProgressBar::hidden() + .with_position(position) + .with_prefix("validate cache") + .with_style(style) + .with_finish(ProgressFinish::AndLeave) + .with_message(msg); + + pb.set_length(total); + pb.enable_steady_tick(Duration::from_millis(100)); + + let pb = if let Some(download_pb) = &self.download_pb { + self.multi_progress.insert_before(download_pb, pb) + } else { + match &self.placement { + Placement::Before(other) => self.multi_progress.insert_before(other, pb), + Placement::After(other) => self.multi_progress.insert_after(other, pb), + Placement::Index(index) => self.multi_progress.insert(*index, pb), + Placement::End => self.multi_progress.add(pb), + } + }; + + self.validation_pb = Some(pb); + } + }; + } + + fn rerender_download(&mut self) { + // Find activate validation entries + let downloading_packages: Vec<_> = self + .packages + .iter() + .filter(|e| e.download_started) + .collect(); + if downloading_packages.is_empty() && self.download_pb.is_none() { + // If there are no packages to validate, we don't need to do anything. + return; + } + + // The total length of the progress bar + let total = downloading_packages + .iter() + .map(|r| r.size.unwrap_or(1)) + .sum::(); + + // The total number of bytes downloaded + let position: u64 = downloading_packages + .iter() + .filter_map(|r| r.download_progress) + .sum(); + + // True if all packages have completed validation and have started downloading. + let completed = self.packages.iter().all(|r| { + r.download_started + && r.download_completed + && (!r.validate_started || r.validate_completed) + }); + let pending = self + .packages + .iter() + .all(|r| !r.download_started || r.download_completed); + + let remaining: Vec<_> = downloading_packages + .into_iter() + .filter(|r| !r.download_completed) + .collect(); + let msg = if remaining.is_empty() { + String::new() + } else { + format_progress_message(remaining) + }; + + let style = self.style(ProgressStyleProperties { + status: if completed { + ProgressStatus::Finished + } else if pending { + ProgressStatus::Paused + } else { + ProgressStatus::Active + }, + progress_type: ProgressType::Bytes, + }); + + // Make sure there is a progress bar. + match &self.download_pb { + Some(pb) => { + pb.set_style(style); + pb.set_length(total); + pb.set_position(position); + pb.set_message(msg); + } + None => { + let pb = ProgressBar::hidden() + .with_position(position) + .with_prefix("download & extract") + .with_style(style) + .with_message(msg) + .with_finish(ProgressFinish::AndLeave); + + pb.set_length(total); + pb.enable_steady_tick(Duration::from_millis(100)); + + let pb = if let Some(validation_pb) = &self.validation_pb { + self.multi_progress.insert_after(validation_pb, pb) + } else { + match &self.placement { + Placement::Before(other) => self.multi_progress.insert_before(other, pb), + Placement::After(other) => self.multi_progress.insert_after(other, pb), + Placement::Index(index) => self.multi_progress.insert(*index, pb), + Placement::End => self.multi_progress.add(pb), + } + }; + + self.download_pb = Some(pb); + } + }; + } +} + +impl Drop for PackageCacheReporterInner { + fn drop(&mut self) { + if let Some(pb) = self.validation_pb.take() { + pb.finish_and_clear(); + } + if let Some(pb) = self.download_pb.take() { + pb.finish_and_clear(); + } + } +} + +fn format_progress_message(remaining: Vec<&ProgressEntry>) -> String { + let mut msg = String::new(); + let largest_package = remaining.iter().max_by_key(|e| e.size.unwrap_or(0)); + if let Some(e) = largest_package { + msg.push_str(&e.name); + } + + let count = remaining.len(); + if count > 1 { + msg.push_str(&format!(" (+{})", count - 1)); + } + + msg +} + +struct ProgressEntry { + /// The name of the package + name: String, + + /// The size of the package in bytes or `None` if we don't know the size. + size: Option, + + validate_started: bool, + validate_completed: bool, + + download_started: bool, + download_progress: Option, + + download_completed: bool, +} + +pub struct PackageCacheReporterEntry { + inner: Arc>, + entry_idx: usize, +} + +impl CacheReporter for PackageCacheReporterEntry { + fn on_validate_start(&self) -> usize { + self.inner.lock().unwrap().on_validate_start(self.entry_idx); + self.entry_idx + } + + fn on_validate_complete(&self, index: usize) { + debug_assert!(index == self.entry_idx); + self.inner + .lock() + .unwrap() + .on_validate_complete(self.entry_idx); + } + + fn on_download_start(&self) -> usize { + self.inner.lock().unwrap().on_download_start(self.entry_idx); + self.entry_idx + } + + fn on_download_progress(&self, index: usize, progress: u64, total: Option) { + debug_assert!(index == self.entry_idx); + self.inner + .lock() + .unwrap() + .on_download_progress(self.entry_idx, progress, total); + } + + fn on_download_completed(&self, index: usize) { + debug_assert!(index == self.entry_idx); + self.inner + .lock() + .unwrap() + .on_download_completed(self.entry_idx); + } +} diff --git a/src/render/resolved_dependencies.rs b/src/render/resolved_dependencies.rs index fd552dcf..0d1088f3 100644 --- a/src/render/resolved_dependencies.rs +++ b/src/render/resolved_dependencies.rs @@ -1,46 +1,55 @@ use std::{ + borrow::Cow, collections::HashMap, fmt::{Display, Formatter}, - fs, - path::Path, str::FromStr, + sync::Arc, }; -use crate::{ - metadata::{BuildConfiguration, Output}, - recipe::parser::Requirements, - tool_configuration, -}; -use indicatif::HumanBytes; -use rattler::package_cache::CacheKey; +use indicatif::{HumanBytes, MultiProgress, ProgressBar}; +use rattler::install::Placement; +use rattler_cache::package_cache::{CacheKey, PackageCache, PackageCacheError}; use rattler_conda_types::{ package::{PackageFile, RunExportsJson}, - MatchSpec, PackageName, ParseStrictness, Platform, RepoDataRecord, StringMatcher, VersionSpec, + version_spec::ParseVersionSpecError, + MatchSpec, PackageName, PackageRecord, ParseStrictness, Platform, RepoDataRecord, + StringMatcher, VersionSpec, }; -use rattler_conda_types::{version_spec::ParseVersionSpecError, PackageRecord}; +use reqwest_middleware::ClientWithMiddleware; use serde::{Deserialize, Serialize}; -use thiserror::Error; - -use super::{pin::PinError, solver::create_environment}; -use crate::recipe::parser::Dependency; -use crate::render::pin::PinArgs; -use crate::render::solver::install_packages; use serde_with::{serde_as, DisplayFromStr}; +use thiserror::Error; +use tokio::sync::{mpsc, Semaphore}; use url::Url; +use super::pin::PinError; +use crate::{ + metadata::{build_reindexed_channels, BuildConfiguration, Output}, + recipe::parser::{Dependency, Requirements}, + render::{ + package_cache_reporter::PackageCacheReporter, + pin::PinArgs, + solver::{install_packages, solve_environment}, + }, + tool_configuration, + tool_configuration::Configuration, +}; + /// A enum to keep track of where a given Dependency comes from #[serde_as] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum DependencyInfo { - /// The dependency is a direct dependency of the package, with a variant applied - /// from the variant config + /// The dependency is a direct dependency of the package, with a variant + /// applied from the variant config Variant(VariantDependency), - /// This is a special pin dependency (e.g. `{{ pin_subpackage('foo', exact=True) }}` + /// This is a special pin dependency (e.g. `{{ pin_subpackage('foo', + /// exact=True) }}` PinSubpackage(PinSubpackageDependency), - /// This is a special run_exports dependency (e.g. `{{ pin_compatible('foo') }}` + /// This is a special run_exports dependency (e.g. `{{ pin_compatible('foo') + /// }}` PinCompatible(PinCompatibleDependency), /// This is a special run_exports dependency from another package @@ -70,7 +79,8 @@ impl From for DependencyInfo { } } -/// This is a special pin dependency (e.g. `{{ pin_subpackage('foo', exact=True) }}` +/// This is a special pin dependency (e.g. `{{ pin_subpackage('foo', exact=True) +/// }}` #[serde_as] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(deny_unknown_fields)] @@ -318,7 +328,8 @@ impl ResolvedDependencies { } /// Collect run exports from this environment - /// If `direct_only` is set to true, only the run exports of the direct dependencies are collected + /// If `direct_only` is set to true, only the run exports of the direct + /// dependencies are collected fn run_exports(&self, direct_only: bool) -> HashMap { let mut result = HashMap::new(); for record in &self.resolved { @@ -409,8 +420,8 @@ pub enum ResolveError { #[error("Failed to resolve dependencies: {0}")] DependencyResolutionError(#[from] anyhow::Error), - #[error("Could not collect run exports: {0}")] - CouldNotCollectRunExports(std::io::Error), + #[error("Could not collect run exports")] + CouldNotCollectRunExports(#[from] PackageCacheError), #[error("Could not parse version spec: {0}")] VersionSpecParseError(#[from] ParseVersionSpecError), @@ -437,8 +448,8 @@ pub enum ResolveError { RefreshChannelError(std::io::Error), } -/// Apply a variant to a dependency list and resolve all pin_subpackage and compiler -/// dependencies +/// Apply a variant to a dependency list and resolve all pin_subpackage and +/// compiler dependencies pub fn apply_variant( raw_specs: &[Dependency], build_configuration: &BuildConfiguration, @@ -528,22 +539,68 @@ pub fn apply_variant( .collect() } -/// Collect run exports from the package cache and add them to the package records. -fn amend_run_exports( +/// Collect run exports from the package cache and add them to the package +/// records. +/// TODO: There are many ways that would allow us to optimize this function. +/// 1. This currently downloads an entire package, but we only need the +/// `run_exports.json`. +/// 2. There are special run_exports.json files available for some channels. +async fn amend_run_exports( records: &mut [RepoDataRecord], - cache_dir: &Path, -) -> Result<(), std::io::Error> { - for pkg in records { + client: ClientWithMiddleware, + package_cache: PackageCache, + multi_progress: MultiProgress, + progress_prefix: impl Into>, + top_level_pb: Option, +) -> Result<(), PackageCacheError> { + let max_concurrent_requests = Arc::new(Semaphore::new(50)); + let (tx, mut rx) = mpsc::channel(50); + + let mut progress = PackageCacheReporter::new( + multi_progress, + top_level_pb.map_or(Placement::End, Placement::After), + ) + .with_prefix(progress_prefix); + + for (pkg_idx, pkg) in records.iter().enumerate() { if pkg.package_record.run_exports.is_some() { // If the package already boasts run exports, we don't need to do anything. continue; } - // TODO: This is a bit fragile, as there is no guarantee how the package cache stores the records. - let cache_key: CacheKey = Into::into(&pkg.package_record); - let pkc = cache_dir.join(cache_key.to_string()); + let progress_reporter = Arc::new(progress.add(pkg)); + + let cache_key = CacheKey::from(&pkg.package_record); + let client = client.clone(); + let url = pkg.url.clone(); + let max_concurrent_requests = max_concurrent_requests.clone(); + let tx = tx.clone(); + let package_cache = package_cache.clone(); + tokio::spawn(async move { + let _permit = max_concurrent_requests + .acquire_owned() + .await + .expect("semaphore error"); + let result = match package_cache + .get_or_fetch_from_url(cache_key, url, client, Some(progress_reporter)) + .await + { + Ok(package_dir) => { + let run_exports = + RunExportsJson::from_package_directory(package_dir.path()).ok(); + Ok((pkg_idx, run_exports)) + } + Err(e) => Err(e), + }; + let _ = tx.send(result).await; + }); + } + + drop(tx); - pkg.package_record.run_exports = RunExportsJson::from_package_directory(pkc).ok(); + while let Some(result) = rx.recv().await { + let (pkg_idx, run_exports) = result?; + records[pkg_idx].package_record.run_exports = run_exports; } Ok(()) @@ -558,31 +615,39 @@ pub async fn install_environments( .as_ref() .ok_or(ResolveError::FinalizedDependencyNotFound)?; - if let Some(build_deps) = dependencies.build.as_ref() { - install_packages( - &build_deps.resolved, - &output.build_configuration.build_platform, - &output.build_configuration.directories.build_prefix, - tool_configuration, - ) - .await?; - } - - if let Some(host_deps) = dependencies.host.as_ref() { - install_packages( - &host_deps.resolved, - &output.build_configuration.host_platform, - &output.build_configuration.directories.host_prefix, - tool_configuration, - ) - .await?; - } + const EMPTY_RECORDS: Vec = Vec::new(); + install_packages( + "build", + dependencies + .build + .as_ref() + .map(|deps| &deps.resolved) + .unwrap_or(&EMPTY_RECORDS), + &output.build_configuration.build_platform, + &output.build_configuration.directories.build_prefix, + tool_configuration, + ) + .await?; + + install_packages( + "host", + dependencies + .host + .as_ref() + .map(|deps| &deps.resolved) + .unwrap_or(&EMPTY_RECORDS), + &output.build_configuration.host_platform, + &output.build_configuration.directories.host_prefix, + tool_configuration, + ) + .await?; Ok(()) } /// This function renders the run exports into `RunExportsJson` format -/// This function applies any variant information or `pin_subpackage` specifications to the run exports. +/// This function applies any variant information or `pin_subpackage` +/// specifications to the run exports. fn render_run_exports( output: &Output, compatibility_specs: &HashMap, @@ -613,11 +678,13 @@ fn render_run_exports( /// This function resolves the dependencies of a recipe. /// To do this, we have to run a couple of steps: /// -/// 1. Apply the variants to the dependencies, and compiler & pin_subpackage specs +/// 1. Apply the variants to the dependencies, and compiler & pin_subpackage +/// specs /// 2. Extend the dependencies with the run exports of the dependencies "above" /// 3. Resolve the dependencies /// 4. Download the packages -/// 5. Extract the run exports from the downloaded packages (for the next environment) +/// 5. Extract the run exports from the downloaded packages (for the next +/// environment) pub(crate) async fn resolve_dependencies( requirements: &Requirements, output: &Output, @@ -626,9 +693,6 @@ pub(crate) async fn resolve_dependencies( ) -> Result { let merge_build_host = output.recipe.build().merge_build_and_host_envs(); - let cache_dir = rattler::default_cache_dir().expect("Could not get default cache dir"); - let pkgs_dir = cache_dir.join("pkgs"); - let mut compatibility_specs = HashMap::new(); let build_env = if !requirements.build.is_empty() && !merge_build_host { @@ -643,10 +707,10 @@ pub(crate) async fn resolve_dependencies( .map(|s| s.spec().clone()) .collect::>(); - let mut resolved = create_environment( + let mut resolved = solve_environment( + "build", &match_specs, &output.build_configuration.build_platform, - &output.build_configuration.directories.build_prefix, channels, tool_configuration, output.build_configuration.channel_priority, @@ -656,7 +720,24 @@ pub(crate) async fn resolve_dependencies( .map_err(ResolveError::from)?; // Add the run exports to the records that don't have them yet. - amend_run_exports(&mut resolved, &pkgs_dir) + tool_configuration + .fancy_log_handler + .wrap_in_progress_async_with_progress("Collecting run exports", |pb| { + amend_run_exports( + &mut resolved, + tool_configuration.client.clone(), + tool_configuration.package_cache.clone(), + tool_configuration + .fancy_log_handler + .multi_progress() + .clone(), + tool_configuration + .fancy_log_handler + .with_indent_levels(" "), + Some(pb), + ) + }) + .await .map_err(ResolveError::CouldNotCollectRunExports)?; resolved.iter().for_each(|r| { @@ -668,8 +749,6 @@ pub(crate) async fn resolve_dependencies( resolved, }) } else { - fs::create_dir_all(&output.build_configuration.directories.build_prefix) - .expect("Could not create build prefix"); None }; @@ -680,7 +759,8 @@ pub(crate) async fn resolve_dependencies( &compatibility_specs, )?; - // Apply the strong run exports from the build environment to the host environment + // Apply the strong run exports from the build environment to the host + // environment let mut build_run_exports = HashMap::new(); if let Some(build_env) = &build_env { build_run_exports.extend(build_env.run_exports(true)); @@ -721,10 +801,10 @@ pub(crate) async fn resolve_dependencies( } let host_env = if !match_specs.is_empty() { - let mut resolved = create_environment( + let mut resolved = solve_environment( + "host", &match_specs, &output.build_configuration.host_platform, - &output.build_configuration.directories.host_prefix, channels, tool_configuration, output.build_configuration.channel_priority, @@ -734,7 +814,24 @@ pub(crate) async fn resolve_dependencies( .map_err(ResolveError::from)?; // Add the run exports to the records that don't have them yet. - amend_run_exports(&mut resolved, &pkgs_dir) + tool_configuration + .fancy_log_handler + .wrap_in_progress_async_with_progress("Collecting run exports", |pb| { + amend_run_exports( + &mut resolved, + tool_configuration.client.clone(), + tool_configuration.package_cache.clone(), + tool_configuration + .fancy_log_handler + .multi_progress() + .clone(), + tool_configuration + .fancy_log_handler + .with_indent_levels(" "), + Some(pb), + ) + }) + .await .map_err(ResolveError::CouldNotCollectRunExports)?; resolved.iter().for_each(|r| { @@ -746,8 +843,6 @@ pub(crate) async fn resolve_dependencies( resolved, }) } else { - fs::create_dir_all(&output.build_configuration.directories.host_prefix) - .expect("Could not create host prefix"); None }; @@ -884,31 +979,35 @@ impl Output { let span = tracing::info_span!("Resolving environments"); let _enter = span.enter(); - let output = if self.finalized_dependencies.is_some() { - tracing::info!("Using finalized dependencies"); + if self.finalized_dependencies.is_some() { + return Ok(self); + } + + let channels = build_reindexed_channels(&self.build_configuration, tool_configuration) + .map_err(ResolveError::RefreshChannelError)?; - // The output already has the finalized dependencies, so we can just use it as-is - install_environments(&self, tool_configuration).await?; - self.clone() - } else { - let channels = self - .reindex_channels() - .map_err(ResolveError::RefreshChannelError)?; - let finalized_dependencies = resolve_dependencies( - self.recipe.requirements(), - &self, - &channels, - tool_configuration, - ) - .await?; - - // The output with the resolved dependencies - Output { - finalized_dependencies: Some(finalized_dependencies), - ..self.clone() - } - }; - Ok(output) + let finalized_dependencies = resolve_dependencies( + self.recipe.requirements(), + &self, + &channels, + tool_configuration, + ) + .await?; + + // The output with the resolved dependencies + Ok(Output { + finalized_dependencies: Some(finalized_dependencies), + ..self.clone() + }) + } + + /// Install the environments of the outputs. Assumes that the dependencies + /// for the environment have already been resolved. + pub async fn install_environments( + &self, + tool_configuration: &Configuration, + ) -> Result<(), ResolveError> { + install_environments(self, tool_configuration).await } } diff --git a/src/render/solver.rs b/src/render/solver.rs index d21c793d..94631854 100644 --- a/src/render/solver.rs +++ b/src/render/solver.rs @@ -2,16 +2,15 @@ use std::{ future::IntoFuture, path::Path, sync::{Arc, Mutex}, - time::Duration, }; +use anyhow::Context; use comfy_table::Table; use futures::FutureExt; use indicatif::{HumanBytes, ProgressBar, ProgressStyle}; use itertools::Itertools; use rattler::install::{DefaultProgressFormatter, IndicatifReporter, Installer}; use rattler_conda_types::{Channel, GenericVirtualPackage, MatchSpec, Platform, RepoDataRecord}; -use rattler_repodata_gateway::Gateway; use rattler_solve::{resolvo::Solver, ChannelPriority, SolveStrategy, SolverImpl, SolverTask}; use rattler_virtual_packages::{VirtualPackage, VirtualPackageOverrides}; use url::Url; @@ -56,10 +55,10 @@ fn print_as_table(packages: &[RepoDataRecord]) { tracing::info!("\n{table}"); } -pub async fn create_environment( +pub async fn solve_environment( + name: &str, specs: &[MatchSpec], target_platform: &Platform, - target_prefix: &Path, channels: &[Url], tool_configuration: &tool_configuration::Configuration, channel_priority: ChannelPriority, @@ -69,7 +68,7 @@ pub async fn create_environment( // clap to deal with this because we need to parse the `channel_config` when // parsing matchspecs. - tracing::info!("\nResolving environment for:\n"); + tracing::info!("\nResolving {name} environment:\n"); tracing::info!(" Platform: {}", target_platform); tracing::info!(" Channels: "); for channel in channels { @@ -119,17 +118,42 @@ pub async fn create_environment( .fancy_log_handler .wrap_in_progress("solving", move || Solver.solve(solver_task))?; - if !tool_configuration.render_only { - install_packages( - &required_packages, - target_platform, - target_prefix, - tool_configuration, - ) - .await?; - } else { - tracing::info!("skipping installation when --render-only is used"); - } + // Print the result as a table + print_as_table(&required_packages); + + Ok(required_packages) +} + +#[allow(clippy::too_many_arguments)] +pub async fn create_environment( + name: &str, + specs: &[MatchSpec], + target_platform: &Platform, + target_prefix: &Path, + channels: &[Url], + tool_configuration: &tool_configuration::Configuration, + channel_priority: ChannelPriority, + solve_strategy: SolveStrategy, +) -> anyhow::Result> { + let required_packages = solve_environment( + name, + specs, + target_platform, + channels, + tool_configuration, + channel_priority, + solve_strategy, + ) + .await?; + + install_packages( + name, + &required_packages, + target_platform, + target_prefix, + tool_configuration, + ) + .await?; Ok(required_packages) } @@ -159,14 +183,16 @@ impl rattler_repodata_gateway::Reporter for GatewayReporter { let progress_bar = self .multi_progress .add(ProgressBar::new(1)) - .with_finish(indicatif::ProgressFinish::AndLeave); - - progress_bar.enable_steady_tick(Duration::from_millis(100)); + .with_finish(indicatif::ProgressFinish::AndLeave) + .with_prefix("Downloading"); // use the configured style if let Some(template) = &self.progress_template { progress_bar.set_style(template.clone()); } + + // progress_bar.enable_steady_tick(Duration::from_millis(100)); + let mut progress_bars = self.progress_bars.lock().unwrap(); progress_bars.push(progress_bar); progress_bars.len() - 1 @@ -230,31 +256,13 @@ pub async fn load_repodatas( specs: &[MatchSpec], tool_configuration: &tool_configuration::Configuration, ) -> anyhow::Result> { - let cache_dir = rattler::default_cache_dir()?; - let download_client = tool_configuration.client.clone(); - - // Get the package names from the matchspecs so we can only load the package - // records that we need. - let gateway = Gateway::builder() - .with_cache_dir(cache_dir.join("repodata")) - .with_client(download_client.clone()) - .finish(); - let channels = channels .iter() .map(|url| Channel::from_url(url.clone())) .collect::>(); - let pb = - ProgressBar::new(50).with_style(tool_configuration.fancy_log_handler.default_bytes_style()); - - let test_pb = tool_configuration - .fancy_log_handler - .multi_progress() - .add(pb); - test_pb.finish(); - - let result = gateway + let result = tool_configuration + .repodata_gateway .query( channels, [*target_platform, Platform::NoArch], @@ -284,55 +292,57 @@ pub async fn load_repodatas( tool_configuration .fancy_log_handler .multi_progress() - .clear()?; + .clear() + .unwrap(); Ok(result) } pub async fn install_packages( - required_packages: &Vec, + name: &str, + required_packages: &[RepoDataRecord], target_platform: &Platform, target_prefix: &Path, tool_configuration: &tool_configuration::Configuration, ) -> anyhow::Result<()> { - let installed_packages = vec![]; - - print_as_table(required_packages); - - if !required_packages.is_empty() { - Installer::new() - .with_download_client(tool_configuration.client.clone()) - .with_target_platform(*target_platform) - .with_installed_packages(installed_packages) - .with_execute_link_scripts(true) - .with_reporter( - IndicatifReporter::builder() - .with_multi_progress( - tool_configuration - .fancy_log_handler - .multi_progress() - .clone(), - ) - .with_formatter( - DefaultProgressFormatter::default().with_prefix( - tool_configuration.fancy_log_handler.with_indent_levels(""), - ), - ) - .finish(), + // Make sure the target prefix exists, regardless of whether we'll actually + // install anything in there. + tokio::fs::create_dir_all(&target_prefix) + .await + .with_context(|| { + format!( + "failed to create target prefix: {}", + target_prefix.display() ) - .install(&target_prefix, required_packages.clone()) - .await?; + })?; + + tracing::info!("\nInstalling {name} environment\n"); + Installer::new() + .with_download_client(tool_configuration.client.clone()) + .with_target_platform(*target_platform) + .with_execute_link_scripts(true) + .with_package_cache(tool_configuration.package_cache.clone()) + .with_reporter( + IndicatifReporter::builder() + .with_multi_progress( + tool_configuration + .fancy_log_handler + .multi_progress() + .clone(), + ) + .with_formatter( + DefaultProgressFormatter::default() + .with_prefix(tool_configuration.fancy_log_handler.with_indent_levels("")), + ) + .finish(), + ) + .install(&target_prefix, required_packages.to_owned()) + .await?; - tracing::info!( - "{} Successfully updated the environment", - console::style(console::Emoji("✔", "")).green(), - ); - } else { - tracing::info!( - "{} Already up to date", - console::style(console::Emoji("✔", "")).green(), - ); - } + tracing::info!( + "{} Successfully updated the {name} environment", + console::style(console::Emoji("✔", "")).green(), + ); Ok(()) } diff --git a/src/script.rs b/src/script.rs index f44de618..ebd1f2b5 100644 --- a/src/script.rs +++ b/src/script.rs @@ -143,6 +143,7 @@ trait Interpreter { async fn run(&self, args: ExecutionArgs) -> Result<(), std::io::Error>; + #[allow(dead_code)] async fn find_interpreter( &self, build_prefix: Option<&PathBuf>, diff --git a/src/source/mod.rs b/src/source/mod.rs index 6dfe6457..22acc8b0 100644 --- a/src/source/mod.rs +++ b/src/source/mod.rs @@ -254,7 +254,7 @@ pub async fn fetch_sources( return Err(SourceError::ValidationFailed); } } - fs::copy(&src_path, &dest_dir.join(file_name))?; + fs::copy(&src_path, dest_dir.join(file_name))?; } else { return Err(SourceError::FileNotFound(src_path)); } diff --git a/src/tool_configuration.rs b/src/tool_configuration.rs index 1121174a..1c9e62ba 100644 --- a/src/tool_configuration.rs +++ b/src/tool_configuration.rs @@ -3,15 +3,18 @@ use std::{path::PathBuf, sync::Arc}; -use crate::console_utils::LoggingOutputHandler; use clap::ValueEnum; +use rattler::package_cache::PackageCache; use rattler_conda_types::ChannelConfig; use rattler_networking::{ authentication_storage::{self, backends::file::FileStorageError}, AuthenticationMiddleware, AuthenticationStorage, }; +use rattler_repodata_gateway::Gateway; use reqwest_middleware::ClientWithMiddleware; +use crate::console_utils::LoggingOutputHandler; + /// The user agent to use for the reqwest client pub const APP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),); @@ -27,7 +30,7 @@ pub enum SkipExisting { } /// Global configuration for the build -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct Configuration { /// If set to a value, a progress bar will be shown pub fancy_log_handler: LoggingOutputHandler, @@ -35,7 +38,8 @@ pub struct Configuration { /// The authenticated reqwest download client to use pub client: ClientWithMiddleware, - /// Set this to true if you want to keep the build directory after the build is done + /// Set this to true if you want to keep the build directory after the build + /// is done pub no_clean: bool, /// Whether to skip the test phase @@ -47,18 +51,22 @@ pub struct Configuration { /// Whether to use bzip2 pub use_bz2: bool, - /// Whether to only render the build output - pub render_only: bool, - /// Whether to skip existing packages pub skip_existing: SkipExisting, /// The channel configuration to use when parsing channels. pub channel_config: ChannelConfig, - /// How many threads to use for compression (only relevant for `.conda` archives). - /// This value is not serialized because the number of threads does not matter for the final result. + /// How many threads to use for compression (only relevant for `.conda` + /// archives). This value is not serialized because the number of + /// threads does not matter for the final result. pub compression_threads: Option, + + /// The package cache to use to store packages in. + pub package_cache: PackageCache, + + /// The repodata gateway to use for querying repodata + pub repodata_gateway: Gateway, } /// Get the authentication storage from the given file @@ -97,21 +105,168 @@ pub fn reqwest_client_from_auth_storage( .build()) } -impl Default for Configuration { - fn default() -> Self { +/// A builder for a [`Configuration`]. +pub struct ConfigurationBuilder { + cache_dir: Option, + fancy_log_handler: Option, + client: Option, + no_clean: bool, + no_test: bool, + use_zstd: bool, + use_bz2: bool, + skip_existing: SkipExisting, + channel_config: Option, + compression_threads: Option, +} + +impl Configuration { + /// Constructs a new builder for the configuration. Using the builder allows + /// customizing the default configuration. + pub fn builder() -> ConfigurationBuilder { + ConfigurationBuilder::new() + } +} + +impl ConfigurationBuilder { + fn new() -> Self { Self { - fancy_log_handler: LoggingOutputHandler::default(), - client: reqwest_client_from_auth_storage(None).expect("failed to create client"), + cache_dir: None, + fancy_log_handler: None, + client: None, no_clean: false, no_test: false, use_zstd: true, - use_bz2: true, - render_only: false, + use_bz2: false, skip_existing: SkipExisting::None, - channel_config: ChannelConfig::default_with_root_dir( - std::env::current_dir().unwrap_or_else(|_err| PathBuf::from("/")), - ), + channel_config: None, compression_threads: None, } } + + /// Set the default cache directory to use for objects that need to be + /// cached. + pub fn with_cache_dir(self, cache_dir: PathBuf) -> Self { + Self { + cache_dir: Some(cache_dir), + ..self + } + } + + /// Set the logging output handler to use for logging + pub fn with_logging_output_handler(self, fancy_log_handler: LoggingOutputHandler) -> Self { + Self { + fancy_log_handler: Some(fancy_log_handler), + ..self + } + } + + /// Set whether to skip outputs that have already been build. + pub fn with_skip_existing(self, skip_existing: SkipExisting) -> Self { + Self { + skip_existing, + ..self + } + } + + /// Set the channel configuration to use. + pub fn with_channel_config(self, channel_config: ChannelConfig) -> Self { + Self { + channel_config: Some(channel_config), + ..self + } + } + + /// Set the number of threads to use for compression, or `None` to use the + /// number of cores. + pub fn with_compression_threads(self, compression_threads: Option) -> Self { + Self { + compression_threads, + ..self + } + } + + /// Sets whether to keep the build output or delete it after the build is + /// done. + pub fn with_keep_build(self, keep_build: bool) -> Self { + Self { + no_clean: keep_build, + ..self + } + } + + /// Sets the request client to use for network requests. + pub fn with_reqwest_client(self, client: ClientWithMiddleware) -> Self { + Self { + client: Some(client), + ..self + } + } + + /// Sets whether tests should be executed. + pub fn with_testing(self, testing_enabled: bool) -> Self { + Self { + no_test: !testing_enabled, + ..self + } + } + + /// Whether downloading repodata as `.zst` files is enabled. + pub fn with_zstd_repodata_enabled(self, zstd_repodata_enabled: bool) -> Self { + Self { + use_zstd: zstd_repodata_enabled, + ..self + } + } + + /// Whether downloading repodata as `.bz2` files is enabled. + pub fn with_bz2_repodata_enabled(self, bz2_repodata_enabled: bool) -> Self { + Self { + use_bz2: bz2_repodata_enabled, + ..self + } + } + + /// Construct a [`Configuration`] from the builder. + pub fn finish(self) -> Configuration { + let cache_dir = self.cache_dir.unwrap_or_else(|| { + rattler_cache::default_cache_dir().expect("failed to determine default cache directory") + }); + let client = self.client.unwrap_or_else(|| { + reqwest_client_from_auth_storage(None).expect("failed to create client") + }); + let package_cache = PackageCache::new(cache_dir.join(rattler_cache::PACKAGE_CACHE_DIR)); + let channel_config = self.channel_config.unwrap_or_else(|| { + ChannelConfig::default_with_root_dir( + std::env::current_dir().unwrap_or_else(|_err| PathBuf::from("/")), + ) + }); + let repodata_gateway = Gateway::builder() + .with_cache_dir(cache_dir.join(rattler_cache::REPODATA_CACHE_DIR)) + .with_package_cache(package_cache.clone()) + .with_client(client.clone()) + .with_channel_config(rattler_repodata_gateway::ChannelConfig { + default: rattler_repodata_gateway::SourceConfig { + jlap_enabled: true, + zstd_enabled: self.use_zstd, + bz2_enabled: self.use_bz2, + cache_action: Default::default(), + }, + per_channel: Default::default(), + }) + .finish(); + + Configuration { + fancy_log_handler: self.fancy_log_handler.unwrap_or_default(), + client, + no_clean: self.no_clean, + no_test: self.no_test, + use_zstd: self.use_zstd, + use_bz2: self.use_bz2, + skip_existing: self.skip_existing, + channel_config, + compression_threads: self.compression_threads, + package_cache, + repodata_gateway, + } + } } diff --git a/src/tui/state.rs b/src/tui/state.rs index 1b785b94..608bade5 100644 --- a/src/tui/state.rs +++ b/src/tui/state.rs @@ -10,7 +10,7 @@ use crate::{ }; /// Representation of a package. -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct Package { pub name: String, pub version: String,