mirror of
https://github.com/esphome/esphome.git
synced 2026-10-14 02:02:51 +00:00
[core] Create the PlatformIO HTTP cache dir before the prefetch resolve threads run (#20579)
This commit is contained in:
@@ -620,12 +620,11 @@ def _make_registry_client() -> Any:
|
||||
elsewhere, not by the PlatformIO registry.
|
||||
"""
|
||||
from platformio.package.manager._registry import PackageManagerRegistryMixin
|
||||
from platformio.project.helpers import get_project_cache_dir
|
||||
from platformio.registry.client import RegistryClient
|
||||
|
||||
# PlatformIO creates its HTTP cache dir without exist_ok, so two builds
|
||||
# making their first registry lookup at once race on it
|
||||
(Path(get_project_cache_dir()) / "http").mkdir(parents=True, exist_ok=True)
|
||||
from esphome.platformio.runner import ensure_http_cache_dir
|
||||
|
||||
ensure_http_cache_dir()
|
||||
|
||||
class _Registry(PackageManagerRegistryMixin):
|
||||
def __init__(self) -> None:
|
||||
|
||||
@@ -841,6 +841,10 @@ def _prefetch(build_dir: Path, env: str) -> None:
|
||||
from platformio.package.meta import PackageCompatibility, PackageSpec
|
||||
from platformio.platform.factory import PlatformFactory
|
||||
|
||||
from esphome.platformio.runner import ensure_http_cache_dir
|
||||
|
||||
# The resolve and install pools each build their own registry client
|
||||
ensure_http_cache_dir()
|
||||
platform_spec, config = _project_platform_and_config(
|
||||
build_dir / "platformio.ini", env
|
||||
)
|
||||
|
||||
@@ -106,6 +106,17 @@ def patch_file_downloader() -> None:
|
||||
FileDownloader.__init__ = patched_init
|
||||
|
||||
|
||||
def ensure_http_cache_dir() -> None:
|
||||
"""Create PlatformIO's HTTP cache dir before anything resolves a package.
|
||||
|
||||
PlatformIO creates it without exist_ok on the first registry lookup, so
|
||||
concurrent lookups (the prefetch's resolve threads, or two builds) race.
|
||||
"""
|
||||
from platformio.project.helpers import get_project_cache_dir
|
||||
|
||||
(Path(get_project_cache_dir()) / "http").mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
def patch_registry_private_packages() -> None:
|
||||
"""Skip PlatformIO's private-package probe; it sleeps ~500 ms per lookup.
|
||||
|
||||
|
||||
@@ -561,6 +561,19 @@ def test_registry_lock_deadline_skips_registration(tmp_path: Path) -> None:
|
||||
manager.set_download_utime.assert_not_called()
|
||||
|
||||
|
||||
def test_prefetch_creates_http_cache_dir_first(
|
||||
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
||||
) -> None:
|
||||
"""Eight resolve threads each build a registry client whose cache
|
||||
init has no exist_ok; the dir must exist before any of them run."""
|
||||
from platformio.project import helpers
|
||||
|
||||
monkeypatch.setattr(helpers, "get_project_cache_dir", lambda: str(tmp_path))
|
||||
with patch.object(pf, "_project_platform_and_config", return_value=(None, None)):
|
||||
pf._prefetch(tmp_path, "testenv")
|
||||
assert (tmp_path / "http").is_dir()
|
||||
|
||||
|
||||
def test_main_interrupt_exits_quietly(tmp_path: Path) -> None:
|
||||
"""Ctrl-C reaches the child via the shared process group; it must exit
|
||||
without a traceback."""
|
||||
|
||||
@@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
import io
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from types import ModuleType
|
||||
from unittest.mock import Mock
|
||||
@@ -110,6 +111,20 @@ def test_main_applies_registry_private_packages_patch(
|
||||
assert order == ["patch", "pio"]
|
||||
|
||||
|
||||
def test_ensure_http_cache_dir_is_idempotent(
|
||||
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
||||
) -> None:
|
||||
"""The dir exists before PlatformIO's non-exist_ok makedirs, and a
|
||||
second caller (another thread or build) does not trip over it."""
|
||||
from platformio.project import helpers
|
||||
|
||||
monkeypatch.setattr(helpers, "get_project_cache_dir", lambda: str(tmp_path / "c"))
|
||||
|
||||
runner.ensure_http_cache_dir()
|
||||
assert (tmp_path / "c" / "http").is_dir()
|
||||
runner.ensure_http_cache_dir()
|
||||
|
||||
|
||||
# Snapshot PlatformIO's own probe at import, before any test can patch it
|
||||
_PIO_PROBE = RegistryClient.__dict__["allowed_private_packages"]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user