Skip to content

Commit bf5021b

Browse files
committed
Fix Linux provider bootstrap paths
Signed-off-by: Nick Sweeting <git@sweeting.me>
1 parent 6ff8baa commit bf5021b

4 files changed

Lines changed: 126 additions & 8 deletions

File tree

abxpkg/binprovider_brew.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,9 +307,27 @@ def default_install_handler(
307307
],
308308
timeout=timeout,
309309
)
310+
proc_output = format_subprocess_output(proc.stdout, proc.stderr)
311+
if (
312+
proc.returncode != 0
313+
and "The `brew link` step did not complete successfully" in proc_output
314+
):
315+
for package in dict.fromkeys(
316+
arg
317+
for arg in install_args
318+
if isinstance(arg, str) and not arg.startswith("-")
319+
):
320+
link_proc = self.exec(
321+
bin_name=installer_bin,
322+
cmd=["link", "--overwrite", package],
323+
timeout=timeout,
324+
)
325+
if link_proc.returncode != 0:
326+
self._raise_proc_error("install", install_args, link_proc)
327+
return proc_output
310328
if proc.returncode != 0:
311329
self._raise_proc_error("install", install_args, proc)
312-
return format_subprocess_output(proc.stdout, proc.stderr)
330+
return proc_output
313331

314332
@remap_kwargs({"packages": "install_args"})
315333
def default_update_handler(

abxpkg/binprovider_cargo.py

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from pathlib import Path
77

88
from pydantic import Field, model_validator, computed_field
9-
from typing import Self
9+
from typing import Self, cast
1010

1111
from .base_types import (
1212
BinProviderName,
@@ -16,11 +16,12 @@
1616
abxpkg_install_root_default,
1717
)
1818
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
2020
from .logging import format_subprocess_output
2121

2222

2323
DEFAULT_CARGO_HOME = Path(os.environ.get("CARGO_HOME", "~/.cargo")).expanduser()
24+
MIN_CARGO_INSTALLER_VERSION = cast(SemVer, SemVer.parse("1.85.0"))
2425

2526

2627
class CargoProvider(BinProvider):
@@ -77,6 +78,64 @@ def setup_PATH(self, no_cache: bool = False) -> None:
7778
self.PATH = self._merge_PATH(*cargo_bin_dirs, PATH=self.PATH, prepend=True)
7879
super().setup_PATH(no_cache=no_cache)
7980

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+
80139
@log_method_call()
81140
def setup(
82141
self,

abxpkg/binprovider_nix.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,20 @@ def default_install_handler(
220220
install_args = install_args or self.get_install_args(bin_name)
221221
installer_bin = self.INSTALLER_BINARY(no_cache=no_cache).loaded_abspath
222222
assert installer_bin
223+
env = {
224+
key: value
225+
for key, value in os.environ.items()
226+
if key not in {"GH_TOKEN", "GITHUB_TOKEN"}
227+
}
228+
nix_config = env.get("NIX_CONFIG", "").rstrip()
229+
env["NIX_CONFIG"] = "\n".join(
230+
line
231+
for line in (
232+
nix_config,
233+
"access-tokens = github.com=",
234+
)
235+
if line
236+
)
223237

224238
proc = self.exec(
225239
bin_name=installer_bin,
@@ -234,6 +248,7 @@ def default_install_handler(
234248
str(self.install_root),
235249
*install_args,
236250
],
251+
env=env,
237252
timeout=timeout,
238253
)
239254
if proc.returncode != 0:
@@ -258,6 +273,20 @@ def default_update_handler(
258273
)
259274
installer_bin = self.INSTALLER_BINARY(no_cache=no_cache).loaded_abspath
260275
assert installer_bin
276+
env = {
277+
key: value
278+
for key, value in os.environ.items()
279+
if key not in {"GH_TOKEN", "GITHUB_TOKEN"}
280+
}
281+
nix_config = env.get("NIX_CONFIG", "").rstrip()
282+
env["NIX_CONFIG"] = "\n".join(
283+
line
284+
for line in (
285+
nix_config,
286+
"access-tokens = github.com=",
287+
)
288+
if line
289+
)
261290

262291
proc = self.exec(
263292
bin_name=installer_bin,
@@ -272,6 +301,7 @@ def default_update_handler(
272301
str(self.install_root),
273302
profile_element,
274303
],
304+
env=env,
275305
timeout=timeout,
276306
)
277307
if proc.returncode != 0:
@@ -296,6 +326,20 @@ def default_uninstall_handler(
296326
)
297327
installer_bin = self.INSTALLER_BINARY(no_cache=no_cache).loaded_abspath
298328
assert installer_bin
329+
env = {
330+
key: value
331+
for key, value in os.environ.items()
332+
if key not in {"GH_TOKEN", "GITHUB_TOKEN"}
333+
}
334+
nix_config = env.get("NIX_CONFIG", "").rstrip()
335+
env["NIX_CONFIG"] = "\n".join(
336+
line
337+
for line in (
338+
nix_config,
339+
"access-tokens = github.com=",
340+
)
341+
if line
342+
)
299343

300344
proc = self.exec(
301345
bin_name=installer_bin,
@@ -310,6 +354,7 @@ def default_uninstall_handler(
310354
str(self.install_root),
311355
profile_element,
312356
],
357+
env=env,
313358
timeout=timeout,
314359
)
315360
if proc.returncode not in (0, 1):

tests/conftest.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ def require_tool(self, tool_name: str) -> str:
9393
str(_abxpkg_executable()),
9494
"--lib=None",
9595
"install",
96-
"--abspath",
9796
tool_name,
9897
],
9998
capture_output=True,
@@ -104,10 +103,7 @@ def require_tool(self, tool_name: str) -> str:
104103
"TERM": "dumb",
105104
},
106105
)
107-
output_lines = [
108-
line.strip() for line in proc.stdout.splitlines() if line.strip()
109-
]
110-
tool_path = output_lines[-1] if output_lines else shutil.which(tool_name)
106+
tool_path = shutil.which(tool_name)
111107
assert proc.returncode == 0 and tool_path, (
112108
f"{tool_name} is required on this host for test-machine integration tests, "
113109
f"and fallback install via abxpkg failed.\n"

0 commit comments

Comments
 (0)