Skip to content

Commit 48cfa5f

Browse files
committed
release: abxpkg 1.11.183
1 parent 5eaa758 commit 48cfa5f

3 files changed

Lines changed: 38 additions & 6 deletions

File tree

abxpkg/binprovider_pnpm.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import json
66
import os
7+
import shlex
78
import sys
89
import tempfile
910
import urllib.parse
@@ -485,22 +486,25 @@ def _refresh_bin_link(
485486
bin_name: BinName | HostBinPath,
486487
target: HostBinPath,
487488
) -> HostBinPath:
488-
"""Recreate the managed shim symlink pointing at the resolved pnpm executable."""
489+
"""Recreate the managed shim wrapper pointing at the resolved pnpm executable."""
489490
link_path = self._linked_bin_path(bin_name)
490491
assert link_path is not None, "_refresh_bin_link requires bin_dir to be set"
491492
link_path.parent.mkdir(parents=True, exist_ok=True)
492-
# Idempotent refresh: skip when shim already points at target.
493+
target_path = Path(target).expanduser().resolve(strict=False)
494+
wrapper = f'#!/bin/sh\nexec {shlex.quote(str(target_path))} "$@"\n'
495+
# Idempotent refresh: skip when shim already runs the target.
493496
# Rewriting on every load() bumps mtime and churns the inode,
494497
# which invalidates fingerprint caches unnecessarily.
495-
if link_path.is_symlink():
498+
if link_path.is_file() and not link_path.is_symlink():
496499
try:
497-
if link_path.readlink() == Path(target):
500+
if link_path.read_text() == wrapper:
498501
return TypeAdapter(HostBinPath).validate_python(link_path)
499502
except OSError:
500503
pass
501504
if link_path.exists() or link_path.is_symlink():
502505
link_path.unlink(missing_ok=True)
503-
link_path.symlink_to(target)
506+
link_path.write_text(wrapper)
507+
link_path.chmod(0o755)
504508
return TypeAdapter(HostBinPath).validate_python(link_path)
505509

506510
def default_search_handler(

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "abxpkg"
3-
version = "1.11.182"
3+
version = "1.11.183"
44
description = "System package manager interfaces with Python type hints"
55
authors = [{name = "Nick Sweeting"}, {name = "ArchiveBox"}]
66
requires-python = ">=3.12,<3.15"

tests/test_pnpmprovider.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging
22
import os
33
import shutil
4+
import subprocess
45
import tempfile
56
from pathlib import Path
67

@@ -11,6 +12,33 @@
1112

1213

1314
class TestPnpmProvider:
15+
def test_refresh_bin_link_preserves_pnpm_shim_basedir_behavior(self):
16+
with tempfile.TemporaryDirectory() as temp_dir:
17+
temp_path = Path(temp_dir)
18+
package_bin_dir = temp_path / "package" / "node_modules" / ".bin"
19+
exposed_bin_dir = temp_path / "bin"
20+
target = package_bin_dir / "demo"
21+
package_bin_dir.mkdir(parents=True)
22+
target.write_text('#!/bin/sh\ncat "$(dirname "$0")/payload.txt"\n')
23+
target.chmod(0o755)
24+
(package_bin_dir / "payload.txt").write_text("ok")
25+
26+
provider = PnpmProvider(
27+
install_root=temp_path / "pnpm",
28+
bin_dir=exposed_bin_dir,
29+
postinstall_scripts=True,
30+
min_release_age=0,
31+
)
32+
33+
exposed = provider._refresh_bin_link("demo", target)
34+
result = subprocess.run(
35+
[str(exposed)],
36+
check=True,
37+
capture_output=True,
38+
text=True,
39+
)
40+
assert result.stdout == "ok"
41+
1442
def test_self_bootstrap_installs_pnpm_when_host_pnpm_is_not_on_path(
1543
self,
1644
test_machine,

0 commit comments

Comments
 (0)