|
6 | 6 | from pathlib import Path |
7 | 7 |
|
8 | 8 | from pydantic import Field, model_validator, computed_field |
9 | | -from typing import Self |
| 9 | +from typing import Self, cast |
10 | 10 |
|
11 | 11 | from .base_types import ( |
12 | 12 | BinProviderName, |
|
16 | 16 | abxpkg_install_root_default, |
17 | 17 | ) |
18 | 18 | from .semver import SemVer |
19 | | -from .binprovider import BinProvider, log_method_call, remap_kwargs |
| 19 | +from .binprovider import BinProvider, EnvProvider, log_method_call, remap_kwargs |
20 | 20 | from .logging import format_subprocess_output |
21 | 21 |
|
22 | 22 |
|
23 | 23 | DEFAULT_CARGO_HOME = Path(os.environ.get("CARGO_HOME", "~/.cargo")).expanduser() |
| 24 | +MIN_CARGO_INSTALLER_VERSION = cast(SemVer, SemVer.parse("1.85.0")) |
24 | 25 |
|
25 | 26 |
|
26 | 27 | class CargoProvider(BinProvider): |
@@ -77,6 +78,64 @@ def setup_PATH(self, no_cache: bool = False) -> None: |
77 | 78 | self.PATH = self._merge_PATH(*cargo_bin_dirs, PATH=self.PATH, prepend=True) |
78 | 79 | super().setup_PATH(no_cache=no_cache) |
79 | 80 |
|
| 81 | + def INSTALLER_BINARY(self, no_cache: bool = False): |
| 82 | + from . import Binary, DEFAULT_PROVIDER_NAMES, PROVIDER_CLASS_BY_NAME |
| 83 | + |
| 84 | + cached_installer = self._INSTALLER_BINARY |
| 85 | + if not no_cache and cached_installer and cached_installer.is_valid: |
| 86 | + cached_version = cached_installer.loaded_version |
| 87 | + if ( |
| 88 | + cached_version is not None |
| 89 | + and cached_version >= MIN_CARGO_INSTALLER_VERSION |
| 90 | + ): |
| 91 | + return cached_installer |
| 92 | + |
| 93 | + loaded = None |
| 94 | + try: |
| 95 | + loaded = super().INSTALLER_BINARY(no_cache=no_cache) |
| 96 | + except Exception: |
| 97 | + loaded = None |
| 98 | + |
| 99 | + if loaded and loaded.loaded_abspath: |
| 100 | + loaded_version = loaded.loaded_version |
| 101 | + if ( |
| 102 | + loaded_version is not None |
| 103 | + and loaded_version >= MIN_CARGO_INSTALLER_VERSION |
| 104 | + ): |
| 105 | + self._INSTALLER_BINARY = loaded |
| 106 | + return loaded |
| 107 | + |
| 108 | + raw_provider_names = os.environ.get("ABXPKG_BINPROVIDERS") |
| 109 | + selected_provider_names = ( |
| 110 | + [provider_name.strip() for provider_name in raw_provider_names.split(",")] |
| 111 | + if raw_provider_names |
| 112 | + else list(DEFAULT_PROVIDER_NAMES) |
| 113 | + ) |
| 114 | + env_provider = EnvProvider(install_root=None, bin_dir=None) |
| 115 | + installer_providers: list[BinProvider] = [ |
| 116 | + env_provider |
| 117 | + if provider_name == "env" |
| 118 | + else PROVIDER_CLASS_BY_NAME[provider_name]() |
| 119 | + for provider_name in selected_provider_names |
| 120 | + if provider_name |
| 121 | + and provider_name in PROVIDER_CLASS_BY_NAME |
| 122 | + and provider_name != self.name |
| 123 | + ] |
| 124 | + if not installer_providers: |
| 125 | + installer_providers = [env_provider] |
| 126 | + |
| 127 | + upgraded = Binary( |
| 128 | + name=self.INSTALLER_BIN, |
| 129 | + min_version=MIN_CARGO_INSTALLER_VERSION, |
| 130 | + binproviders=installer_providers, |
| 131 | + ).install(no_cache=no_cache) |
| 132 | + if upgraded and upgraded.loaded_abspath: |
| 133 | + self._INSTALLER_BINARY = upgraded |
| 134 | + return upgraded |
| 135 | + |
| 136 | + assert loaded is not None |
| 137 | + return loaded |
| 138 | + |
80 | 139 | @log_method_call() |
81 | 140 | def setup( |
82 | 141 | self, |
|
0 commit comments