Skip to content

Commit 85efd95

Browse files
committed
split dependency binaries and installed binaries properly
1 parent f3b3524 commit 85efd95

15 files changed

Lines changed: 610 additions & 106 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ cache_dir = <deno_root>/.cache or user_cache_path("deno", "abxpkg")
914914
Source: [`abxpkg/binprovider_bash.py`](./abxpkg/binprovider_bash.py) • Tests: [`tests/test_bashprovider.py`](./tests/test_bashprovider.py)
915915

916916
```python
917-
INSTALLER_BIN = "sh"
917+
INSTALLER_BIN = "bash"
918918
PATH = ""
919919
bash_root = $ABXPKG_BASH_ROOT or $ABXPKG_LIB_DIR/bash
920920
bash_bin_dir = <bash_root>/bin

abxpkg/binprovider.py

Lines changed: 27 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545

4646
from .semver import SemVer
4747
from .base_types import (
48+
DEFAULT_LIB_DIR,
4849
BinName,
4950
BinDirPath,
5051
HostBinPath,
@@ -468,6 +469,7 @@ class CacheRecord(TypedDict):
468469
loaded_version: str
469470
loaded_sha256: str
470471
loaded_euid: int
472+
cache_kind: str
471473
provider_name: str
472474
resolved_provider_name: str
473475
bin_name: str
@@ -566,12 +568,18 @@ def load_cached_binary(
566568
resolved_abspath = str(Path(abspath).expanduser().resolve(strict=False))
567569
cached_install_args = cached_record.get("install_args")
568570
resolved_provider_name = cached_record.get("resolved_provider_name")
571+
cache_kind = cached_record.get("cache_kind")
569572
if not isinstance(resolved_provider_name, str):
570573
resolved_provider_name = self.name
574+
if not isinstance(cache_kind, str):
575+
cache_kind = (
576+
"dependency" if str(bin_name) == str(self.INSTALLER_BIN) else "binary"
577+
)
571578
primary_fingerprint = fingerprints[0]
572579
if (
573580
cached_record.get("provider_name") != self.name
574581
or cached_record.get("resolved_provider_name") != resolved_provider_name
582+
or cached_record.get("cache_kind") != cache_kind
575583
or cached_record.get("bin_name") != str(bin_name)
576584
or cached_record.get("abspath") != resolved_abspath
577585
or not isinstance(cached_install_args, list)
@@ -585,6 +593,7 @@ def load_cached_binary(
585593
"loaded_version": str(version),
586594
"loaded_sha256": str(sha256),
587595
"loaded_euid": euid,
596+
"cache_kind": cache_kind,
588597
"provider_name": self.name,
589598
"resolved_provider_name": resolved_provider_name,
590599
"bin_name": str(bin_name),
@@ -624,11 +633,9 @@ def write_cached_binary(
624633
loaded_version: SemVer,
625634
loaded_sha256: Sha256,
626635
resolved_provider_name: str | None = None,
636+
cache_kind: str = "binary",
627637
) -> tuple[MTimeNs, EUID] | None:
628638
derived_env_path = self.derived_env_path
629-
if derived_env_path is None:
630-
return None
631-
632639
cache_info = self.get_cache_info(bin_name, abspath)
633640
if cache_info is None:
634641
return None
@@ -637,14 +644,14 @@ def write_cached_binary(
637644
if fingerprints is None:
638645
return None
639646

640-
cache = load_derived_cache(derived_env_path)
641647
resolved_abspath = str(Path(abspath).expanduser().resolve(strict=False))
642648
primary_fingerprint = fingerprints[0]
643-
cache[self._cache_key(bin_name, abspath)] = {
649+
record: dict[str, object] = {
644650
"fingerprint": fingerprints,
645651
"loaded_version": str(loaded_version),
646652
"loaded_sha256": str(loaded_sha256),
647653
"loaded_euid": primary_fingerprint["euid"],
654+
"cache_kind": cache_kind,
648655
"provider_name": self.name,
649656
"resolved_provider_name": resolved_provider_name or self.name,
650657
"bin_name": str(bin_name),
@@ -656,13 +663,19 @@ def write_cached_binary(
656663
"mtime": primary_fingerprint["mtime_ns"],
657664
"euid": primary_fingerprint["euid"],
658665
}
666+
if derived_env_path is None:
667+
return None
668+
cache = load_derived_cache(derived_env_path)
669+
cache[self._cache_key(bin_name, abspath)] = record
659670
save_derived_cache(derived_env_path, cache)
660671
return (
661672
TypeAdapter(MTimeNs).validate_python(fingerprints[0]["mtime_ns"]),
662673
TypeAdapter(EUID).validate_python(fingerprints[0]["euid"]),
663674
)
664675

665-
_cache: dict[str, dict[str, Any]] | None = None
676+
_cache: dict[str, dict[str, Any]] | None = (
677+
None # Per-method in-memory cache populated by @binprovider_cache during the current process only.
678+
)
666679
_INSTALLER_BINARY: ShallowBinary | None = (
667680
None # cached by INSTALLER_BINARY property after first resolution
668681
)
@@ -854,36 +867,8 @@ def INSTALLER_BINARY(self, no_cache: bool = False) -> ShallowBinary:
854867
if loaded.loaded_binprovider is not None
855868
else self.name
856869
),
870+
cache_kind="dependency",
857871
)
858-
try:
859-
first_line = loaded.loaded_abspath.read_text(
860-
encoding="utf-8",
861-
errors="ignore",
862-
).splitlines()[0]
863-
except Exception:
864-
first_line = ""
865-
if "node" in first_line:
866-
node_loaded = Binary(
867-
name="node",
868-
binproviders=manual_installer_providers,
869-
).load(no_cache=no_cache)
870-
if (
871-
node_loaded
872-
and node_loaded.loaded_abspath
873-
and node_loaded.loaded_version
874-
and node_loaded.loaded_sha256
875-
):
876-
self.write_cached_binary(
877-
"node",
878-
node_loaded.loaded_abspath,
879-
node_loaded.loaded_version,
880-
node_loaded.loaded_sha256,
881-
resolved_provider_name=(
882-
node_loaded.loaded_binprovider.name
883-
if node_loaded.loaded_binprovider is not None
884-
else self.name
885-
),
886-
)
887872
self._INSTALLER_BINARY = loaded
888873
return self._INSTALLER_BINARY
889874
except Exception:
@@ -906,36 +891,8 @@ def INSTALLER_BINARY(self, no_cache: bool = False) -> ShallowBinary:
906891
if loaded.loaded_binprovider is not None
907892
else self.name
908893
),
894+
cache_kind="dependency",
909895
)
910-
try:
911-
first_line = loaded.loaded_abspath.read_text(
912-
encoding="utf-8",
913-
errors="ignore",
914-
).splitlines()[0]
915-
except Exception:
916-
first_line = ""
917-
if "node" in first_line:
918-
node_loaded = Binary(
919-
name="node",
920-
binproviders=installer_providers,
921-
).load(no_cache=no_cache)
922-
if (
923-
node_loaded
924-
and node_loaded.loaded_abspath
925-
and node_loaded.loaded_version
926-
and node_loaded.loaded_sha256
927-
):
928-
self.write_cached_binary(
929-
"node",
930-
node_loaded.loaded_abspath,
931-
node_loaded.loaded_version,
932-
node_loaded.loaded_sha256,
933-
resolved_provider_name=(
934-
node_loaded.loaded_binprovider.name
935-
if node_loaded.loaded_binprovider is not None
936-
else self.name
937-
),
938-
)
939896
self._INSTALLER_BINARY = loaded
940897
return self._INSTALLER_BINARY
941898
except Exception:
@@ -2344,7 +2301,9 @@ class EnvProvider(BinProvider):
23442301
DEFAULT_ENV_PATH # Ambient runtime PATH; no provider-specific setup step.
23452302
)
23462303
install_root: Path | None = Field(
2347-
default_factory=lambda: abxpkg_install_root_default("env"),
2304+
default_factory=lambda: (
2305+
abxpkg_install_root_default("env") or (DEFAULT_LIB_DIR / "env")
2306+
),
23482307
)
23492308

23502309
overrides: "BinProviderOverrides" = {
@@ -2434,6 +2393,7 @@ def INSTALLER_BINARY(self, no_cache: bool = False) -> ShallowBinary:
24342393
if loaded.loaded_binprovider is not None
24352394
else self.name
24362395
),
2396+
cache_kind="dependency",
24372397
)
24382398
self._INSTALLER_BINARY = loaded
24392399
return self._INSTALLER_BINARY
@@ -2643,6 +2603,7 @@ def write_cached_binary(
26432603
loaded_version: SemVer,
26442604
loaded_sha256: Sha256,
26452605
resolved_provider_name: str | None = None,
2606+
cache_kind: str = "binary",
26462607
) -> tuple[MTimeNs, EUID] | None:
26472608
if self._is_managed_by_other_provider(abspath):
26482609
self.invalidate_cache(bin_name)
@@ -2670,6 +2631,7 @@ def write_cached_binary(
26702631
loaded_version,
26712632
loaded_sha256,
26722633
resolved_provider_name,
2634+
cache_kind,
26732635
)
26742636

26752637

abxpkg/binprovider_ansible.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from pathlib import Path
1212
from typing import Any
1313

14+
from .binary import Binary
1415
from .base_types import BinProviderName, PATHStr, BinName, InstallArgs
1516
from .semver import SemVer
1617
from .shallowbinary import ShallowBinary
@@ -294,6 +295,45 @@ def INSTALLER_BINARY(self, no_cache: bool = False) -> ShallowBinary:
294295

295296
loaded = self.load(bin_name="ansible-playbook", no_cache=no_cache)
296297
if loaded and loaded.loaded_abspath:
298+
from . import DEFAULT_PROVIDER_NAMES, PROVIDER_CLASS_BY_NAME
299+
300+
raw_provider_names = os.environ.get("ABXPKG_BINPROVIDERS")
301+
selected_provider_names = (
302+
[
303+
provider_name.strip()
304+
for provider_name in raw_provider_names.split(",")
305+
]
306+
if raw_provider_names
307+
else list(DEFAULT_PROVIDER_NAMES)
308+
)
309+
python_loaded = Binary(
310+
name="python",
311+
binproviders=[
312+
PROVIDER_CLASS_BY_NAME[provider_name]()
313+
for provider_name in selected_provider_names
314+
if provider_name
315+
and provider_name in PROVIDER_CLASS_BY_NAME
316+
and provider_name != self.name
317+
],
318+
).load(no_cache=no_cache)
319+
if (
320+
python_loaded
321+
and python_loaded.loaded_abspath
322+
and python_loaded.loaded_version
323+
and python_loaded.loaded_sha256
324+
):
325+
self.write_cached_binary(
326+
"python",
327+
python_loaded.loaded_abspath,
328+
python_loaded.loaded_version,
329+
python_loaded.loaded_sha256,
330+
resolved_provider_name=(
331+
python_loaded.loaded_binprovider.name
332+
if python_loaded.loaded_binprovider is not None
333+
else self.name
334+
),
335+
cache_kind="dependency",
336+
)
297337
self._INSTALLER_BINARY = loaded
298338
return loaded
299339

abxpkg/binprovider_bash.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
class BashProvider(EnvProvider):
3737
name: BinProviderName = "bash"
3838
_log_emoji = "🧪"
39-
INSTALLER_BIN: BinName = "sh"
39+
INSTALLER_BIN: BinName = "bash"
4040

4141
PATH: PATHStr = "" # Starts empty; setup_PATH() replaces it with bin_dir only.
4242
postinstall_scripts: bool | None = Field(default=None, repr=False)

abxpkg/binprovider_gem.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from pydantic import Field, model_validator, computed_field
99
from typing import Self
1010

11+
from .binary import Binary
1112
from .base_types import (
1213
BinProviderName,
1314
PATHStr,
@@ -75,6 +76,46 @@ def setup_PATH(self, no_cache: bool = False) -> None:
7576
self.PATH = self._merge_PATH(bin_dir, PATH=self.PATH)
7677
super().setup_PATH(no_cache=no_cache)
7778

79+
def INSTALLER_BINARY(self, no_cache: bool = False):
80+
from . import DEFAULT_PROVIDER_NAMES, PROVIDER_CLASS_BY_NAME
81+
82+
loaded = super().INSTALLER_BINARY(no_cache=no_cache)
83+
raw_provider_names = os.environ.get("ABXPKG_BINPROVIDERS")
84+
selected_provider_names = (
85+
[provider_name.strip() for provider_name in raw_provider_names.split(",")]
86+
if raw_provider_names
87+
else list(DEFAULT_PROVIDER_NAMES)
88+
)
89+
ruby_loaded = Binary(
90+
name="ruby",
91+
binproviders=[
92+
PROVIDER_CLASS_BY_NAME[provider_name]()
93+
for provider_name in selected_provider_names
94+
if provider_name
95+
and provider_name in PROVIDER_CLASS_BY_NAME
96+
and provider_name != self.name
97+
],
98+
).load(no_cache=no_cache)
99+
if (
100+
ruby_loaded
101+
and ruby_loaded.loaded_abspath
102+
and ruby_loaded.loaded_version
103+
and ruby_loaded.loaded_sha256
104+
):
105+
self.write_cached_binary(
106+
"ruby",
107+
ruby_loaded.loaded_abspath,
108+
ruby_loaded.loaded_version,
109+
ruby_loaded.loaded_sha256,
110+
resolved_provider_name=(
111+
ruby_loaded.loaded_binprovider.name
112+
if ruby_loaded.loaded_binprovider is not None
113+
else self.name
114+
),
115+
cache_kind="dependency",
116+
)
117+
return loaded
118+
78119
@log_method_call()
79120
def setup(
80121
self,

abxpkg/binprovider_goget.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ def INSTALLER_BINARY(self, no_cache: bool = False):
152152
if loaded.loaded_binprovider is not None
153153
else self.name
154154
),
155+
cache_kind="dependency",
155156
)
156157
self._INSTALLER_BINARY = loaded
157158
return self._INSTALLER_BINARY

0 commit comments

Comments
 (0)