Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ PATH = "" # prepends cargo_root/bin and cargo_home/bi
cargo_root = None # set this for hermetic installs
```

- Install root: set `install_root=Path(...)` or `install_root=Path(...)` for isolated installs under `<cargo_root>/bin`; otherwise installs go through `cargo_home`.
- Install root: set `install_root=Path(...)` or `cargo_root=Path(...)` for isolated installs under `<cargo_root>/bin`; otherwise installs go through `cargo_home`.
- Auto-switching: none.
- `dry_run`: shared behavior.
- Security: `min_release_age` and `postinstall_scripts=False` are unsupported and are ignored with a warning if explicitly requested.
Expand Down
33 changes: 33 additions & 0 deletions abxpkg/binary.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,39 @@ def load(
)
raise BinaryLoadError(self.name, provider_names, errors) from inner_exc

@validate_call
@log_method_call(include_result=True)
def load_or_install(
self,
binproviders: list[BinProviderName] | None = None,
no_cache: bool = False,
dry_run: bool | None = None,
postinstall_scripts: bool | None = None,
min_release_age: float | None = None,
**extra_overrides,
) -> Self:
"""Try ``load()`` first; fall back to ``install()`` if no provider
resolves the binary. Returns the loaded/installed copy of ``self``.
"""
try:
loaded = self.load(
binproviders=binproviders,
no_cache=no_cache,
**extra_overrides,
)
except BinaryLoadError:
loaded = self
if loaded.is_valid and not no_cache:
return loaded
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
Outdated
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
Outdated
return self.install(
binproviders=binproviders,
no_cache=no_cache,
dry_run=dry_run,
postinstall_scripts=postinstall_scripts,
min_release_age=min_release_age,
**extra_overrides,
)

@validate_call
@log_method_call(include_result=True)
def update(
Expand Down
10 changes: 9 additions & 1 deletion abxpkg/binprovider.py
Original file line number Diff line number Diff line change
Expand Up @@ -1732,10 +1732,18 @@ def drop_privileges():
sudo_proc.stderr,
)

# When running as root but dropping to a non-root user (e.g. brew),
# use the target user's HOME/LOGNAME/USER env so the dropped-privilege
# subprocess finds its own cache/config dirs instead of root's.
dropped_env = (
sudo_env
if current_euid == 0 and run_as_uid != current_euid
else fallback_env
)
proc = subprocess.run(
cmd,
cwd=str(cwd_path),
env=fallback_env,
env=dropped_env,
preexec_fn=drop_privileges,
**kwargs,
)
Expand Down
20 changes: 20 additions & 0 deletions abxpkg/binprovider_brew.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,26 @@ def _refresh_bin_link(
link_path = self._linked_bin_path(bin_name)
assert link_path is not None, "_refresh_bin_link requires bin_dir to be set"
link_path.parent.mkdir(parents=True, exist_ok=True)
# When running as root but brew itself drops to its owner uid via
# ``self.exec``, we also need the managed shim dir (and its parents)
# traversable by that target uid so version probes / load() calls from
# the dropped-privilege subprocess can reach the symlink.
current_euid = os.geteuid()
target_uid = self.EUID
if current_euid == 0 and target_uid not in (0, current_euid):
try:
pw_record = self.get_pw_record(target_uid)
os.chown(link_path.parent, target_uid, pw_record.pw_gid)
except Exception:
pass
walk_path = link_path.parent
while walk_path != walk_path.parent:
try:
mode = walk_path.stat().st_mode
walk_path.chmod(mode | 0o055)
except Exception:
break
walk_path = walk_path.parent
if link_path.exists() or link_path.is_symlink():
link_path.unlink(missing_ok=True)
link_path.symlink_to(target)
Expand Down
Loading