Skip to content

Commit a4ad2c6

Browse files
committed
perf: Replace slow pip freeze with fast SHA caching and direct FS scanning
- Implemented per-Python SHA computation and caching (`_per_python_sha`) to entirely bypass subprocess checks when the lock hasn't changed. - Refactored `_interp_matches_lock` to directly scan `dist-info` and `.omnipkg_versions` on the filesystem instead of invoking `pip freeze`, which was significantly slower and blind to omnipkg bubble structures. - Added `PYTHONPATH` fallback logic in `_install_with_skip_fallback` to ensure pip eggs are correctly loaded during installations. - Bumped `uv` vendor submodule. Modified: • src/omnipkg/integration/reproducible.py (+78/-19 lines) [gitship-generated]
1 parent c10654c commit a4ad2c6

2 files changed

Lines changed: 78 additions & 19 deletions

File tree

src/omnipkg/_vendor/uv

src/omnipkg/integration/reproducible.py

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2041,9 +2041,17 @@ def safe_input(prompt, default="", auto_value=None):
20412041
print(f" Skipping Python {ver}.")
20422042
continue
20432043

2044-
# Skip if already matches lock
2045-
if _interp_matches_lock(py_path, active):
2044+
# === PER-PYTHON SHA SKIP (fast path — no subprocess) ===
2045+
_plat = meta.get("platform", platform.system())
2046+
_py_sha = _per_python_sha(ver, active, bubbles, _plat)
2047+
if _per_python_sha_check(lock_path, ver, _py_sha):
2048+
print(f" ✅ Python {ver} already synced (SHA match) — skipping.")
2049+
continue
2050+
2051+
# Skip if already matches lock (slower live pip freeze check)
2052+
if _interp_matches_lock(py_path, active, bubbles):
20462053
print(f" ✅ Python {ver} already matches lock — skipping.")
2054+
_per_python_sha_write(lock_path, ver, _py_sha) # cache for next run
20472055
continue
20482056

20492057
print(f"\n 🧹 Clearing site-packages: {sp_path}")
@@ -2101,6 +2109,7 @@ def safe_input(prompt, default="", auto_value=None):
21012109
_run_cmd([f"8pkg{short}", "install", f"{pkg}=={bver}"], check=False)
21022110

21032111
print(f"\n ✅ Python {ver} synced.")
2112+
_per_python_sha_write(lock_path, ver, _py_sha)
21042113

21052114
# Stop daemon only after all shim calls are done — keeping it alive during
21062115
# the loop prevents execv fallback on adopt/bubble/doctor calls.
@@ -2122,26 +2131,69 @@ def safe_input(prompt, default="", auto_value=None):
21222131

21232132
# ── sync helpers ──────────────────────────────────────────────────────────────
21242133

2125-
def _interp_matches_lock(py_path: Path, active: dict) -> bool:
2126-
"""Returns True if the interpreter's installed packages match the lock active dict."""
2134+
def _per_python_sha(ver: str, active: dict, bubbles: dict, plat: str) -> str:
2135+
"""Compute a deterministic SHA for a single Python version's sync state."""
2136+
active_str = ",".join(f"{k}=={v}" for k, v in sorted(active.items()))
2137+
bubble_str = ";".join(
2138+
f"{k}:{','.join(sorted(vs))}" for k, vs in sorted(bubbles.items())
2139+
)
2140+
raw = f"{ver}|{plat}|{active_str}|{bubble_str}"
2141+
return hashlib.sha256(raw.encode()).hexdigest()[:16]
2142+
2143+
def _per_python_sha_path(lock_path: Path, ver: str) -> Path:
2144+
"""Sidecar file path: <lock_dir>/per_python/<lock_stem>/<ver>.sha"""
2145+
return lock_path.parent / "per_python" / lock_path.stem / f"{ver}.sha"
2146+
2147+
def _per_python_sha_check(lock_path: Path, ver: str, sha: str) -> bool:
2148+
"""Returns True if the stored SHA matches — safe to skip this Python."""
21272149
try:
2128-
r = subprocess.run(
2129-
[str(py_path), "-m", "pip", "freeze"],
2130-
capture_output=True, text=True, timeout=30,
2131-
)
2132-
if r.returncode != 0:
2150+
p = _per_python_sha_path(lock_path, ver)
2151+
return p.exists() and p.read_text().strip() == sha
2152+
except Exception:
2153+
return False
2154+
2155+
def _per_python_sha_write(lock_path: Path, ver: str, sha: str) -> None:
2156+
"""Write SHA sidecar after a successful sync."""
2157+
try:
2158+
p = _per_python_sha_path(lock_path, ver)
2159+
p.parent.mkdir(parents=True, exist_ok=True)
2160+
p.write_text(sha)
2161+
except Exception:
2162+
pass # non-fatal — just means next run won't skip
2163+
2164+
def _interp_matches_lock(py_path: Path, active: dict, bubbles: dict | None = None) -> bool:
2165+
"""
2166+
FS-based check — no pip subprocess.
2167+
Scans dist-info for active packages and .omnipkg_versions/ for bubbles.
2168+
pip freeze is intentionally NOT used: it is blind to omnipkg bubble structure.
2169+
"""
2170+
try:
2171+
sp = _site_packages_for(py_path)
2172+
if not sp or not sp.exists():
21332173
return False
2134-
installed = {}
2135-
for line in r.stdout.splitlines():
2136-
if "==" in line:
2137-
k, v = line.split("==", 1)
2138-
installed[k.lower().replace("-", "_")] = v.strip()
2139-
_SKIP = {"omnipkg", "pip", "setuptools", "wheel", "pkg_resources"}
2174+
2175+
_SKIP = {"omnipkg", "pip", "setuptools", "wheel", "pkg-resources", "pkg_resources"}
2176+
2177+
# ── active packages: scan dist-info on fs ────────────────────────────
2178+
installed = _scan_active_from_fs(sp)
21402179
for pkg, ver in active.items():
2141-
if pkg.lower().replace("-", "_") in _SKIP:
2180+
norm = re.sub(r"[-_.]+", "-", pkg).lower()
2181+
if norm in _SKIP:
21422182
continue
2143-
if installed.get(pkg.lower().replace("-", "_")) != ver:
2183+
if installed.get(norm) != ver:
21442184
return False
2185+
2186+
# ── bubbles: scan .omnipkg_versions/ on fs ───────────────────────────
2187+
if bubbles:
2188+
mv_base = sp / ".omnipkg_versions"
2189+
installed_bubbles = _scan_bubbles_from_fs(mv_base)
2190+
for pkg, versions in bubbles.items():
2191+
norm = re.sub(r"[-_.]+", "-", pkg).lower()
2192+
installed_vers = set(installed_bubbles.get(norm, []))
2193+
for bver in versions:
2194+
if bver not in installed_vers:
2195+
return False
2196+
21452197
return True
21462198
except Exception:
21472199
return False
@@ -2216,6 +2268,13 @@ def _extract_bad_packages(error_text: str) -> set[str]:
22162268
skipped: list[str] = []
22172269

22182270
while remaining:
2271+
import glob as _glob, os as _os
2272+
_sp = Path(py_path).parent.parent / "lib"
2273+
_egg_paths = _glob.glob(str(_sp / "python*/site-packages/pip-*.egg"))
2274+
_env = _os.environ.copy()
2275+
if _egg_paths:
2276+
_existing = _env.get("PYTHONPATH", "")
2277+
_env["PYTHONPATH"] = _os.pathsep.join(_egg_paths + ([_existing] if _existing else []))
22192278
cmd = [str(py_path), "-m", "pip", "install", "--no-deps", "--no-cache-dir"] + remaining
22202279
print(f" $ {' '.join(cmd[:4])} ... ({len(remaining)} packages)")
22212280

@@ -2225,7 +2284,7 @@ def _extract_bad_packages(error_text: str) -> set[str]:
22252284
cmd,
22262285
stdout=subprocess.PIPE,
22272286
stderr=subprocess.PIPE,
2228-
text=True, encoding="utf-8", errors="replace",
2287+
text=True, encoding="utf-8", errors="replace", env=_env,
22292288
)
22302289
assert proc.stdout is not None
22312290
assert proc.stderr is not None

0 commit comments

Comments
 (0)