4"""Install the repository-pinned uv binary from a verified release asset."""
6from __future__
import annotations
25from collections.abc
import Callable, Iterator
26from contextlib
import contextmanager
27from pathlib
import Path, PurePosixPath
28from typing
import NoReturn, Protocol, Self
30sys.path.insert(0, str(Path(__file__).resolve().parent))
31import bootstrap_uv_exec
33ROOT = Path(__file__).resolve().parents[2]
34DEFAULT_MANIFEST = Path(__file__).with_name(
"uv_release.json")
35DEFAULT_CACHE = ROOT /
".tools" /
"uv"
36MAX_ASSET_BYTES = 128 * 1024 * 1024
37MAX_UV_BINARY_BYTES = 96 * 1024 * 1024
38SHA256_HEX_LENGTH = hashlib.sha256().digest_size * 2
39ZIP_UNIX_CREATE_SYSTEM = 3
40PRIVATE_ARCHIVE_MODE = stat.S_IRUSR | stat.S_IWUSR
41PRIVATE_EXECUTABLE_MODE = PRIVATE_ARCHIVE_MODE | stat.S_IXUSR
42PUBLIC_ARCHIVE_MODE = PRIVATE_ARCHIVE_MODE | stat.S_IRGRP | stat.S_IROTH
43PUBLIC_EXECUTABLE_MODE = PUBLIC_ARCHIVE_MODE | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
44EXPECTED_PUBLIC_MODES = (0o644, 0o755)
47class BootstrapError(RuntimeError):
48 """Represent a fail-closed uv bootstrap error."""
51class CacheApplyRequiredError(BootstrapError):
52 """Report authenticated cache drift that a supported apply can repair."""
55class CacheMetadataChangedError(BootstrapError):
56 """Report that authenticated descriptor metadata changed before use completed."""
59class CachePathBindingError(BootstrapError):
60 """Report that a cache pathname no longer names its authenticated inode."""
63class DownloadHeaders(Protocol):
64 """Describe the response header operation used by the downloader."""
66 def get(self, name: str, default: str |
None =
None) -> str |
None:
67 """Return one response header."""
70class DownloadResponse(Protocol):
71 """Describe the bounded subset of an HTTP response used here."""
73 headers: DownloadHeaders
75 def read(self, size: int = -1) -> bytes:
76 """Read at most size response bytes."""
78 def __enter__(self) -> Self:
79 """Enter the response context."""
81 def __exit__(self, *_args: object) ->
None:
82 """Leave the response context."""
85DownloadOpener = Callable[..., DownloadResponse]
88def fail(message: str) -> NoReturn:
89 """Stop bootstrap processing with one user-facing policy error."""
90 raise BootstrapError(message)
93def load_manifest(path: Path) -> dict[str, object]:
94 """Load and validate the single uv release manifest."""
96 document = json.loads(path.read_text(encoding=
"ascii"))
97 except (OSError, UnicodeError, json.JSONDecodeError)
as exc:
98 fail(f
"cannot read uv manifest {path}: {exc}")
99 if not isinstance(document, dict):
100 fail(
"uv manifest root must be an object")
101 if document.get(
"schema") != 1:
102 fail(
"uv manifest schema must be 1")
103 if document.get(
"repository") !=
"astral-sh/uv":
104 fail(
"uv manifest repository must be astral-sh/uv")
105 version = document.get(
"version")
106 if not isinstance(version, str)
or re.fullmatch(
r"[0-9]+\.[0-9]+\.[0-9]+", version)
is None:
107 fail(f
"uv manifest has an invalid release version: {version!r}")
108 assets = document.get(
"assets")
109 if not isinstance(assets, dict)
or not assets:
110 fail(
"uv manifest has no asset table")
114def normalized_machine(machine: str) -> str:
115 """Map operating-system architecture spellings to release triples."""
116 value = machine.lower()
117 if value
in {
"amd64",
"x64",
"x86_64"}:
119 if value
in {
"aarch64",
"arm64"}:
121 fail(f
"unsupported architecture: {machine}")
124def has_musl_loader(directories: tuple[Path, ...]) -> bool:
125 """Return whether a known musl loader name resolves to a regular file."""
127 path.is_file()
for directory
in directories
for path
in directory.glob(
"ld-musl-*.so.1")
131def detect_linux_libc() -> str:
132 """Distinguish the two supported Linux release ABIs without executing host tools."""
133 libc_name = platform.libc_ver()[0].lower()
134 if "musl" in libc_name:
136 if libc_name
in {
"glibc",
"gnu libc"}:
138 abi_values =
" ".join(
139 str(sysconfig.get_config_var(name)
or "").lower()
for name
in (
"MULTIARCH",
"HOST_GNU_TYPE")
141 if "musl" in abi_values:
143 if "linux-gnu" in abi_values:
145 if has_musl_loader((Path(
"/lib"), Path(
"/usr/lib"))):
147 fail(
"unsupported or unidentified Linux libc")
150def asset_key(system: str, machine: str, libc_name: str |
None =
None) -> str:
151 """Return the manifest key for a supported host."""
152 architecture = normalized_machine(machine)
153 if system ==
"Linux":
154 selected_libc = libc_name
or detect_linux_libc()
155 if selected_libc
not in {
"gnu",
"musl"}:
156 fail(f
"unsupported Linux libc: {selected_libc}")
157 return f
"Linux|{architecture}|{selected_libc}"
158 if system
in {
"Darwin",
"Windows"}:
159 return f
"{system}|{architecture}"
160 fail(f
"unsupported operating system: {system}")
163def expected_asset_name(key: str) -> str:
164 """Derive the only acceptable official asset name for a host key."""
165 system, architecture, *libc_value = key.split(
"|")
166 if system ==
"Darwin" and not libc_value:
167 return f
"uv-{architecture}-apple-darwin.tar.gz"
168 if system ==
"Windows" and not libc_value:
169 return f
"uv-{architecture}-pc-windows-msvc.zip"
170 if system ==
"Linux" and len(libc_value) == 1
and libc_value[0]
in {
"gnu",
"musl"}:
171 return f
"uv-{architecture}-unknown-linux-{libc_value[0]}.tar.gz"
172 fail(f
"invalid uv platform key: {key}")
176 manifest: dict[str, object],
177 system: str |
None =
None,
178 machine: str |
None =
None,
179 libc_name: str |
None =
None,
180) -> tuple[str, str, str]:
181 """Select one release URL, name, and digest from the manifest."""
182 key = asset_key(system
or platform.system(), machine
or platform.machine(), libc_name)
183 assets = manifest[
"assets"]
184 if not isinstance(assets, dict)
or key
not in assets:
185 fail(f
"uv manifest has no asset for {key}")
187 if not isinstance(record, dict):
188 fail(f
"uv asset record for {key} must be an object")
189 name = record.get(
"name")
190 digest = record.get(
"sha256")
191 if not isinstance(name, str)
or not isinstance(digest, str):
192 fail(f
"uv asset record for {key} is incomplete")
193 if len(digest) != SHA256_HEX_LENGTH
or any(char
not in "0123456789abcdef" for char
in digest):
194 fail(f
"uv asset record for {key} has an invalid SHA-256")
195 expected_name = expected_asset_name(key)
196 if name != expected_name:
197 fail(f
"uv asset record for {key} must name {expected_name}, got {name}")
198 version = manifest[
"version"]
199 repository = manifest[
"repository"]
200 if not isinstance(version, str)
or not isinstance(repository, str):
201 fail(
"uv manifest release identity is malformed")
202 release_url = f
"https://github.com/{repository}/releases/download/{version}"
203 return f
"{release_url}/{name}", name, digest
206def verify_payload(payload: bytes, expected: str) ->
None:
207 """Reject release bytes whose SHA-256 does not match the manifest."""
208 actual = hashlib.sha256(payload).hexdigest()
209 if actual != expected:
210 fail(f
"uv asset SHA-256 mismatch: expected {expected}, got {actual}")
213def require_bounded_executable(stream: object, declared_size: int) -> bytes:
214 """Read one executable member without allowing archive inflation."""
215 if declared_size < 1
or declared_size > MAX_UV_BINARY_BYTES:
216 fail(f
"uv executable size is outside policy: {declared_size} bytes")
217 if not hasattr(stream,
"read"):
218 fail(
"uv executable archive member is not readable")
219 payload = stream.read(MAX_UV_BINARY_BYTES + 1)
220 if not isinstance(payload, bytes)
or len(payload) != declared_size:
221 fail(
"uv executable size does not match archive metadata")
225def executable_bytes(payload: bytes, asset_name: str) -> bytes:
226 """Read the one exact uv member from a verified release archive."""
227 archive_stem = asset_name.removesuffix(
".tar.gz").removesuffix(
".zip")
228 executable =
"uv.exe" if asset_name.endswith(
".zip")
else "uv"
229 expected_member = f
"{archive_stem}/{executable}"
230 if asset_name.endswith(
".zip"):
232 with zipfile.ZipFile(io.BytesIO(payload))
as archive:
233 names = archive.namelist()
234 executable_members = [
235 name
for name
in names
if PurePosixPath(name).name == executable
237 if names.count(expected_member) != 1
or executable_members != [expected_member]:
238 fail(f
"uv archive lacks exact member {expected_member}")
239 info = archive.getinfo(expected_member)
241 fail(f
"uv archive member is not a file: {expected_member}")
242 unix_type = stat.S_IFMT(info.external_attr >> 16)
243 if info.create_system == ZIP_UNIX_CREATE_SYSTEM
and unix_type
not in {
247 fail(f
"uv archive member is not a regular file: {expected_member}")
248 with archive.open(info)
as source:
249 return require_bounded_executable(source, info.file_size)
250 except zipfile.BadZipFile
as exc:
251 fail(f
"invalid uv release archive: {exc}")
253 with tarfile.open(fileobj=io.BytesIO(payload), mode=
"r:gz")
as archive:
254 members = archive.getmembers()
255 executable_members = [
256 member
for member
in members
if PurePosixPath(member.name).name == executable
258 matches = [member
for member
in members
if member.name == expected_member]
259 if len(matches) != 1
or executable_members != matches
or not matches[0].isfile():
260 fail(f
"uv archive lacks exact regular member {expected_member}")
261 source = archive.extractfile(matches[0])
263 fail(
"uv executable could not be read from archive")
265 return require_bounded_executable(source, matches[0].size)
266 except tarfile.TarError
as exc:
267 fail(f
"invalid uv release archive: {exc}")
270def download_payload(url: str, opener: DownloadOpener = urllib.request.urlopen) -> bytes:
271 """Download one bounded release asset and report transport failures."""
272 if not url.startswith(
"https://github.com/astral-sh/uv/releases/download/"):
273 fail(f
"refusing non-official uv release URL: {url}")
274 request = urllib.request.Request(
275 url, headers={
"User-Agent":
"ra8-firmware-uv-bootstrap"}
278 with opener(request, timeout=60)
as response:
279 length = response.headers.get(
"Content-Length")
280 if length
is not None and int(length) > MAX_ASSET_BYTES:
281 fail(f
"uv asset exceeds {MAX_ASSET_BYTES} bytes")
282 payload = response.read(MAX_ASSET_BYTES + 1)
283 except BootstrapError:
285 except (OSError, ValueError)
as exc:
286 fail(f
"cannot download pinned uv asset {url}: {exc}")
287 if len(payload) > MAX_ASSET_BYTES:
288 fail(f
"uv asset exceeds {MAX_ASSET_BYTES} bytes")
292def reject_symlink_components(
293 cache_root: Path, destination: Path, anchor: Path |
None =
None
295 """Reject symlinks from a trusted anchor through the cache destination."""
296 cache_root = cache_root.absolute()
297 destination = destination.absolute()
300 cache_root.relative_to(ROOT)
302 anchor = cache_root.parent
305 anchor = anchor.absolute()
307 relative = destination.relative_to(cache_root)
309 fail(f
"uv destination escapes cache root: {destination}")
311 cache_relative = cache_root.relative_to(anchor)
313 fail(f
"uv cache root escapes trusted anchor: {cache_root}")
315 if current.is_symlink():
316 fail(f
"uv cache anchor is a symlink: {current}")
317 for component
in (*cache_relative.parts, *relative.parts):
319 if current.is_symlink():
320 fail(f
"symlink in uv cache path: {current}")
323def cache_destination(cache_root: Path, version: str, asset_name: str) -> Path:
324 """Return the platform-specific executable cache path."""
325 archive_stem = asset_name.removesuffix(
".tar.gz").removesuffix(
".zip")
326 executable =
"uv.exe" if asset_name.endswith(
".zip")
else "uv"
327 return cache_root / version / archive_stem / executable
330def validated_cached_payload(archive_path: Path, digest: str) -> bytes:
331 """Read and authenticate a retained release archive on every reuse."""
332 if os.name ==
"posix":
333 descriptor = open_cache_fd(archive_path)
335 payload, _ = read_stable_fd(descriptor, archive_path, MAX_ASSET_BYTES)
338 verify_payload(payload, digest)
340 if archive_path.is_symlink()
or not archive_path.is_file():
341 fail(f
"verified uv archive is missing: {archive_path}")
343 payload = archive_path.read_bytes()
344 except OSError
as exc:
345 fail(f
"cannot read cached uv archive {archive_path}: {exc}")
346 verify_payload(payload, digest)
350def validated_cached_binary(
351 archive_path: Path, destination: Path, asset_name: str, digest: str
353 """Authenticate the retained archive and compare its executable byte-for-byte."""
354 if os.name ==
"posix":
355 with authenticated_cache_fds(
356 archive_path, destination, asset_name, digest
358 return authenticated[2]
359 payload = validated_cached_payload(archive_path, digest)
360 binary = executable_bytes(payload, asset_name)
361 if destination.is_symlink()
or not destination.is_file():
362 fail(f
"cached uv executable is missing: {destination}")
364 installed = destination.read_bytes()
365 except OSError
as exc:
366 fail(f
"cannot read cached uv executable {destination}: {exc}")
367 if not binary
or installed != binary:
368 fail(f
"cached uv executable differs from verified archive: {destination}")
372def write_atomic(path: Path, payload: bytes, executable: bool =
False) ->
None:
373 """Write one cache artifact through a held no-follow parent."""
374 if os.name !=
"posix":
375 fail(
"authenticated uv cache writes require POSIX; use WSL on Windows")
376 mode = PRIVATE_EXECUTABLE_MODE
if executable
else PRIVATE_ARCHIVE_MODE
378 bootstrap_uv_exec.write_atomic_nofollow(path, payload, mode)
379 except bootstrap_uv_exec.UvExecError
as exc:
383def open_cache_fd(path: Path) -> int:
384 """Open one POSIX cache artifact through a no-follow parent walk."""
386 return bootstrap_uv_exec.open_regular_nofollow(path)
387 except bootstrap_uv_exec.UvExecError
as exc:
391def read_stable_fd(descriptor: int, path: Path, maximum: int) -> tuple[bytes, os.stat_result]:
392 """Read one bounded regular FD and reject concurrent inode mutation."""
393 before = os.fstat(descriptor)
395 with os.fdopen(os.dup(descriptor),
"rb")
as source:
396 payload = source.read(maximum + 1)
397 after = os.fstat(descriptor)
398 except OSError
as exc:
399 fail(f
"cannot read cached uv artifact {path}: {exc}")
400 stable = (
"st_dev",
"st_ino",
"st_size",
"st_mtime_ns",
"st_ctime_ns",
"st_nlink")
401 if any(getattr(before, field) != getattr(after, field)
for field
in stable):
402 fail(f
"cached uv artifact changed while authenticating: {path}")
403 if len(payload) > maximum:
404 fail(f
"cached uv artifact exceeds policy: {path}")
405 return payload, after
409def authenticated_cache_fds(
410 archive_path: Path, destination: Path, asset_name: str, digest: str
411) -> Iterator[tuple[int, int, bytes, os.stat_result, os.stat_result]]:
412 """Hold exact authenticated archive and executable descriptors."""
413 archive_fd = open_cache_fd(archive_path)
416 destination_fd = open_cache_fd(destination)
417 payload, archive_state = read_stable_fd(archive_fd, archive_path, MAX_ASSET_BYTES)
418 verify_payload(payload, digest)
419 binary = executable_bytes(payload, asset_name)
420 installed, installed_state = read_stable_fd(
421 destination_fd, destination, MAX_UV_BINARY_BYTES
423 if not binary
or installed != binary:
424 fail(f
"cached uv executable differs from verified archive: {destination}")
425 yield archive_fd, destination_fd, binary, archive_state, installed_state
427 if destination_fd >= 0:
428 os.close(destination_fd)
432def verify_fd_mode(path: Path, descriptor: int, mode: int) ->
None:
433 """Require an exact authenticated descriptor to carry one shared mode."""
434 state = os.fstat(descriptor)
435 if stat.S_IMODE(state.st_mode) != mode:
436 message = f
"cached uv permissions require an apply: {path}"
437 raise CacheApplyRequiredError(message)
440def probe_authenticated_uv(binary: bytes, version: str) ->
None:
441 """Probe an immutable authenticated uv snapshot for its exact version."""
443 completed = bootstrap_uv_exec.run_uv_snapshot(
444 binary, [
"--version"], capture_output=
True, timeout=10
446 except bootstrap_uv_exec.UvExecError
as exc:
448 if completed.returncode != 0
or completed.stdout.split()[:2] != [
"uv", version]:
449 fail(f
"installed uv failed its version probe: {completed.stderr.strip()}")
452def propagate_child_status(status: int) -> int:
453 """Return an exit code or terminate this wrapper through the child's signal."""
457 unmask = getattr(signal,
"pthread_sigmask",
None)
458 if signum >= signal.NSIG
or unmask
is None:
459 fail(
"authenticated uv child returned an unsupported signal status")
460 uncatchable = (signal.SIGKILL, signal.SIGSTOP)
462 if signum
not in uncatchable:
463 signal.signal(signum, signal.SIG_DFL)
464 unmask(signal.SIG_UNBLOCK, {signum})
465 os.kill(os.getpid(), signum)
466 except (OSError, ValueError)
as exc:
467 fail(f
"cannot propagate authenticated uv child signal: {exc}")
468 fail(
"authenticated uv child signal did not terminate the wrapper")
471def verify_fd_unchanged(path: Path, descriptor: int, expected: os.stat_result) ->
None:
472 """Require cache identity and content metadata to remain authenticated."""
473 current = os.fstat(descriptor)
474 stable = (
"st_dev",
"st_ino",
"st_size",
"st_mtime_ns",
"st_ctime_ns",
"st_nlink")
475 if any(getattr(expected, field) != getattr(current, field)
for field
in stable):
476 message = f
"cached uv artifact changed after authenticating: {path}"
477 raise CacheMetadataChangedError(message)
480def verify_fd_path(path: Path, descriptor: int, mode: int) ->
None:
481 """Require one chmod target to remain the exact regular path opened."""
482 descriptor_state = os.fstat(descriptor)
485 reopened = open_cache_fd(path)
486 path_state = os.fstat(reopened)
487 except (BootstrapError, OSError)
as exc:
488 message = f
"cached uv path moved during permission repair: {path}: {exc}"
489 raise CachePathBindingError(message)
from exc
493 same_file = (descriptor_state.st_dev, descriptor_state.st_ino) == (
497 if not stat.S_ISREG(path_state.st_mode)
or path_state.st_nlink != 1
or not same_file:
498 message = f
"cached uv path moved during permission repair: {path}"
499 raise CachePathBindingError(message)
500 if stat.S_IMODE(descriptor_state.st_mode) != mode:
501 fail(f
"cached uv permissions did not converge: {path}")
504def normalize_cached_modes(
505 archive_path: Path, destination: Path, asset_name: str, digest: str
507 """Authenticate exact POSIX FDs, then make those public release bytes shared."""
508 if os.name !=
"posix":
511 with authenticated_cache_fds(archive_path, destination, asset_name, digest)
as descriptors:
512 archive_fd, destination_fd, _, _, _ = descriptors
513 os.fchmod(archive_fd, PUBLIC_ARCHIVE_MODE)
514 os.fchmod(destination_fd, PUBLIC_EXECUTABLE_MODE)
515 verify_fd_path(archive_path, archive_fd, PUBLIC_ARCHIVE_MODE)
516 verify_fd_path(destination, destination_fd, PUBLIC_EXECUTABLE_MODE)
517 except OSError
as exc:
518 fail(f
"cannot normalize authenticated uv cache permissions: {exc}")
521def verify_cached_modes(archive_path: Path, destination: Path) ->
None:
522 """Require exact shared POSIX modes without mutating either cache file."""
523 if os.name !=
"posix":
526 (archive_path, PUBLIC_ARCHIVE_MODE),
527 (destination, PUBLIC_EXECUTABLE_MODE),
530 state = os.lstat(path)
531 except OSError
as exc:
532 fail(f
"cannot inspect cached uv permissions {path}: {exc}")
533 if not stat.S_ISREG(state.st_mode)
or state.st_nlink != 1:
534 fail(f
"cached uv artifact is not one single-link regular file: {path}")
535 if stat.S_IMODE(state.st_mode) != mode:
536 message = f
"cached uv permissions require an apply: {path}"
537 raise CacheApplyRequiredError(message)
540def verify_cached_uv(manifest_path: Path, cache_root: Path) -> Path:
541 """Authenticate and probe an existing cache without network access or writes."""
542 manifest = load_manifest(manifest_path)
543 _, asset_name, digest = select_asset(manifest)
544 version = manifest[
"version"]
545 if not isinstance(version, str):
546 fail(
"uv manifest version is not a string")
547 cache_root = cache_root.absolute()
548 destination = cache_destination(cache_root, version, asset_name)
549 archive_path = destination.parent / asset_name
550 reject_symlink_components(cache_root, archive_path)
551 reject_symlink_components(cache_root, destination)
552 if not archive_path.exists()
and not destination.exists():
553 message = f
"authenticated uv cache requires an apply: {destination}"
554 raise CacheApplyRequiredError(message)
555 if not archive_path.exists():
556 fail(f
"cached uv has no authenticated archive: {destination}")
557 if not destination.exists():
558 validated_cached_payload(archive_path, digest)
559 message = f
"authenticated uv cache requires an apply: {destination}"
560 raise CacheApplyRequiredError(message)
561 if os.name !=
"posix":
562 validated_cached_binary(archive_path, destination, asset_name, digest)
564 with authenticated_cache_fds(archive_path, destination, asset_name, digest)
as descriptors:
565 archive_fd, destination_fd, binary, archive_state, installed_state = descriptors
566 verify_fd_mode(archive_path, archive_fd, PUBLIC_ARCHIVE_MODE)
567 verify_fd_mode(destination, destination_fd, PUBLIC_EXECUTABLE_MODE)
568 probe_authenticated_uv(binary, version)
569 verify_fd_unchanged(archive_path, archive_fd, archive_state)
570 verify_fd_unchanged(destination, destination_fd, installed_state)
571 verify_fd_path(archive_path, archive_fd, PUBLIC_ARCHIVE_MODE)
572 verify_fd_path(destination, destination_fd, PUBLIC_EXECUTABLE_MODE)
579 arguments: list[str],
583 """Run uv only from bytes authenticated and snapshotted by this process."""
585 fail(
"authenticated uv execution requires at least one uv argument")
586 if os.name !=
"posix":
587 fail(
"authenticated uv execution requires POSIX; use WSL on Windows")
589 ensure_uv(manifest_path, cache_root)
591 else verify_cached_uv(manifest_path, cache_root)
593 manifest = load_manifest(manifest_path)
594 _, asset_name, digest = select_asset(manifest)
595 archive_path = destination.parent / asset_name
596 with authenticated_cache_fds(archive_path, destination, asset_name, digest)
as descriptors:
597 archive_fd, destination_fd, binary, archive_state, installed_state = descriptors
598 verify_fd_mode(archive_path, archive_fd, PUBLIC_ARCHIVE_MODE)
599 verify_fd_mode(destination, destination_fd, PUBLIC_EXECUTABLE_MODE)
601 completed = bootstrap_uv_exec.run_uv_snapshot(binary, arguments)
602 except bootstrap_uv_exec.UvExecError
as exc:
604 verify_fd_unchanged(archive_path, archive_fd, archive_state)
605 verify_fd_unchanged(destination, destination_fd, installed_state)
606 verify_fd_path(archive_path, archive_fd, PUBLIC_ARCHIVE_MODE)
607 verify_fd_path(destination, destination_fd, PUBLIC_EXECUTABLE_MODE)
608 return propagate_child_status(completed.returncode)
611def ensure_uv(manifest_path: Path, cache_root: Path) -> Path:
612 """Download, verify, and atomically install uv when it is not cached."""
613 manifest = load_manifest(manifest_path)
614 url, asset_name, digest = select_asset(manifest)
615 version = manifest[
"version"]
616 if not isinstance(version, str):
617 fail(
"uv manifest version is not a string")
618 cache_root = cache_root.absolute()
619 destination = cache_destination(cache_root, version, asset_name)
620 archive_path = destination.parent / asset_name
621 reject_symlink_components(cache_root, archive_path)
622 reject_symlink_components(cache_root, destination)
624 if not (archive_path.exists()
and destination.exists()):
625 if destination.exists():
626 fail(f
"cached uv has no authenticated archive: {destination}")
627 if archive_path.exists():
628 payload = validated_cached_payload(archive_path, digest)
630 payload = download_payload(url)
631 verify_payload(payload, digest)
632 binary = executable_bytes(payload, asset_name)
634 fail(
"uv release archive contained an empty executable")
635 if not archive_path.exists():
636 write_atomic(archive_path, payload)
637 write_atomic(destination, binary, executable=
True)
638 normalize_cached_modes(archive_path, destination, asset_name, digest)
639 return verify_cached_uv(manifest_path, cache_root)
642def synthetic_archive(
645 member_name: str |
None =
None,
646 member_kind: str =
"file",
648 """Create a small release-shaped archive for offline negative tests."""
649 stem = asset_name.removesuffix(
".tar.gz").removesuffix(
".zip")
650 executable =
"uv.exe" if asset_name.endswith(
".zip")
else "uv"
651 name = member_name
or f
"{stem}/{executable}"
652 output = io.BytesIO()
653 if asset_name.endswith(
".zip"):
654 with zipfile.ZipFile(output, mode=
"w")
as archive:
655 if member_kind ==
"symlink":
656 info = zipfile.ZipInfo(name)
657 info.create_system = 3
658 info.external_attr = (stat.S_IFLNK | 0o777) << 16
659 archive.writestr(info, b
"elsewhere")
661 archive.writestr(name, binary)
662 if member_kind ==
"duplicate":
663 archive.writestr(f
"other/{executable}", binary)
664 result = bytearray(output.getvalue())
665 if member_kind ==
"oversized":
666 local_header = result.index(b
"PK\x03\x04")
667 central_header = result.index(b
"PK\x01\x02")
668 struct.pack_into(
"<I", result, local_header + 22, MAX_UV_BINARY_BYTES + 1)
669 struct.pack_into(
"<I", result, central_header + 24, MAX_UV_BINARY_BYTES + 1)
671 with tarfile.open(fileobj=output, mode=
"w:gz")
as archive:
672 info = tarfile.TarInfo(name)
673 if member_kind ==
"symlink":
674 info.type = tarfile.SYMTYPE
675 info.linkname =
"elsewhere"
676 archive.addfile(info)
678 info.size = len(binary)
679 archive.addfile(info, io.BytesIO(binary))
680 if member_kind ==
"duplicate":
681 duplicate = tarfile.TarInfo(f
"other/{executable}")
682 duplicate.size = len(binary)
683 archive.addfile(duplicate, io.BytesIO(binary))
684 return output.getvalue()
687def expect_bootstrap_error(
688 action: Callable[[], object], label: str, message: str |
None =
None
690 """Require one negative selftest action to fail closed."""
693 except BootstrapError
as error:
694 if message
is not None and message
not in str(error):
695 fail(f
"selftest: {label} returned unexpected error: {error}")
697 fail(f
"selftest: {label} passed unexpectedly")
700def archive_selftest() -> None:
701 """Exercise exact-member and malformed-archive handling."""
703 "uv-x86_64-unknown-linux-gnu.tar.gz",
704 "uv-x86_64-pc-windows-msvc.zip",
706 payload = synthetic_archive(asset_name, b
"verified-uv")
707 if executable_bytes(payload, asset_name) != b
"verified-uv":
708 fail(f
"selftest: valid archive failed for {asset_name}")
709 expect_bootstrap_error(
710 lambda asset=asset_name: executable_bytes(
711 synthetic_archive(asset, b
"verified-uv",
"wrong/place/uv"), asset
713 f
"wrong member path for {asset_name}",
715 expect_bootstrap_error(
716 lambda asset=asset_name: executable_bytes(synthetic_archive(asset, b
""), asset),
717 f
"empty executable for {asset_name}",
719 expect_bootstrap_error(
720 lambda asset=asset_name: executable_bytes(
721 synthetic_archive(asset, b
"verified-uv", member_kind=
"duplicate"), asset
723 f
"duplicate executable basename for {asset_name}",
725 expect_bootstrap_error(
726 lambda asset=asset_name: executable_bytes(b
"not an archive", asset),
727 f
"corrupt archive for {asset_name}",
730 "uv-x86_64-unknown-linux-gnu.tar.gz",
731 "uv-x86_64-pc-windows-msvc.zip",
733 expect_bootstrap_error(
734 lambda asset=asset_name: executable_bytes(
735 synthetic_archive(asset, b
"", member_kind=
"symlink"), asset
737 f
"symlink archive member for {asset_name}",
739 zip_name =
"uv-x86_64-pc-windows-msvc.zip"
740 expect_bootstrap_error(
741 lambda: executable_bytes(
742 synthetic_archive(zip_name, b
"uv", member_kind=
"oversized"), zip_name
744 "oversized executable metadata",
749def cache_selftest() -> None:
750 """Exercise archive reauthentication and cache path hardening."""
751 asset_name =
"uv-x86_64-unknown-linux-gnu.tar.gz"
752 archive = synthetic_archive(asset_name, b
"verified-uv")
753 digest = hashlib.sha256(archive).hexdigest()
754 with tempfile.TemporaryDirectory(prefix=
"ra8-uv-cache-test-")
as raw:
756 directory = root /
"0.0.0" / asset_name.removesuffix(
".tar.gz")
757 directory.mkdir(parents=
True)
758 archive_path = directory / asset_name
759 destination = directory /
"uv"
760 archive_path.write_bytes(archive)
761 destination.write_bytes(b
"verified-uv")
762 validated_cached_binary(archive_path, destination, asset_name, digest)
764 destination.write_bytes(b
"mutated")
765 expect_bootstrap_error(
766 lambda: validated_cached_binary(archive_path, destination, asset_name, digest),
767 "mutated cached executable",
769 destination.write_bytes(b
"verified-uv")
770 archive_path.write_bytes(b
"mutated")
771 expect_bootstrap_error(
772 lambda: validated_cached_binary(archive_path, destination, asset_name, digest),
773 "mutated cached archive",
775 archive_path.unlink()
776 expect_bootstrap_error(
777 lambda: validated_cached_binary(archive_path, destination, asset_name, digest),
778 "binary without authenticated archive",
781 outside = root /
"outside"
782 outside.write_bytes(archive)
783 archive_path.symlink_to(outside)
784 expect_bootstrap_error(
785 lambda: validated_cached_payload(archive_path, digest),
786 "symlinked cached archive",
788 archive_path.unlink()
789 real_parent = root /
"real-parent"
791 linked_parent = root /
"linked-parent"
792 linked_parent.symlink_to(real_parent, target_is_directory=
True)
793 expect_bootstrap_error(
794 lambda: reject_symlink_components(root, linked_parent /
"uv"),
795 "symlinked cache parent",
797 workspace = root /
"workspace"
799 external_tools = root /
"external-tools"
800 external_tools.mkdir()
801 (workspace /
".tools").symlink_to(external_tools, target_is_directory=
True)
802 expect_bootstrap_error(
803 lambda: reject_symlink_components(
804 workspace /
".tools" /
"uv",
805 workspace /
".tools" /
"uv" /
"0.0.0" /
"uv",
808 "symlinked ancestor before cache root",
812def cache_mode_selftest() -> None:
813 """Run the adjacent adversarial mode suite under the bootstrap module."""
814 namespace = runpy.run_path(
815 str(Path(__file__).with_name(
"bootstrap_uv_mode_selftest.py")),
816 init_globals={
"bootstrap": sys.modules[__name__]},
818 runner = namespace.get(
"run_mode_selftest")
819 if not callable(runner):
820 fail(
"uv mode selftest module has no runner")
824def manifest_matrix_selftest(manifest: dict[str, object]) ->
None:
825 """Prove every supported mapping and reject unsupported/swapped records."""
832 "Linux|aarch64|musl",
836 assets = manifest[
"assets"]
837 if not isinstance(assets, dict)
or set(assets) != expected_keys:
838 fail(
"selftest: manifest platform matrix is incomplete or over-broad")
839 for key
in expected_keys:
840 system, machine, *libc_value = key.split(
"|")
841 _, name, digest = select_asset(
842 manifest, system, machine, libc_value[0]
if libc_value
else None
844 if name != expected_asset_name(key)
or len(digest) != SHA256_HEX_LENGTH:
845 fail(f
"selftest: malformed selected asset for {key}")
846 for system, machine, libc_name
in (
847 (
"FreeBSD",
"x86_64",
None),
848 (
"Linux",
"riscv64",
"gnu"),
849 (
"Linux",
"x86_64",
"uclibc"),
851 expect_bootstrap_error(
852 lambda s=system, m=machine, libc=libc_name: select_asset(manifest, s, m, libc),
853 f
"unsupported host {system}/{machine}/{libc_name}",
855 mutated = json.loads(json.dumps(manifest))
856 mutated[
"assets"][
"Linux|x86_64|gnu"][
"name"] =
"uv-aarch64-unknown-linux-gnu.tar.gz"
857 expect_bootstrap_error(
858 lambda: select_asset(mutated,
"Linux",
"x86_64",
"gnu"),
859 "architecture-swapped asset",
863def transport_and_libc_selftest(manifest: dict[str, object]) ->
None:
864 """Exercise timeout handling and non-executing musl-loader detection."""
866 def timeout_opener(*_args: object, **_kwargs: object) -> DownloadResponse:
867 message =
"timed out"
868 raise TimeoutError(message)
870 url, _, _ = select_asset(manifest,
"Linux",
"x86_64",
"gnu")
871 expect_bootstrap_error(
872 lambda: download_payload(url, timeout_opener),
874 "cannot download pinned uv asset",
876 with tempfile.TemporaryDirectory(prefix=
"ra8-musl-detect-")
as raw:
877 directory = Path(raw)
878 loader_target = directory /
"loader"
879 loader_target.write_bytes(b
"musl")
880 (directory /
"ld-musl-x86_64.so.1").symlink_to(loader_target)
881 if not has_musl_loader((directory,)):
882 fail(
"selftest: resolving musl loader symlink was rejected")
885def run_selftest() -> None:
886 """Exercise supported mappings and all important fail-closed paths."""
887 manifest = load_manifest(DEFAULT_MANIFEST)
888 manifest_matrix_selftest(manifest)
889 expect_bootstrap_error(
lambda: verify_payload(b
"tampered",
"0" * 64),
"checksum mismatch")
890 payload = b
"uv-test-payload"
891 verify_payload(payload, hashlib.sha256(payload).hexdigest())
892 transport_and_libc_selftest(manifest)
895 cache_mode_selftest()
896 print(
"bootstrap_uv.py --selftest: PASS")
899def parse_args() -> argparse.Namespace:
900 """Parse the small bootstrap command-line interface."""
901 parser = argparse.ArgumentParser(description=__doc__)
902 mode = parser.add_mutually_exclusive_group(required=
True)
903 mode.add_argument(
"--ensure", action=
"store_true", help=
"install and print pinned uv")
907 help=
"authenticate an existing cache without downloads or writes",
910 "--check-cache-modes",
912 help=
"check shared POSIX cache modes without authenticating or writing",
914 mode.add_argument(
"--print-path", action=
"store_true", help=
"print cache path without writes")
917 nargs=argparse.REMAINDER,
919 help=
"run uv from an authenticated existing-cache snapshot",
923 nargs=argparse.REMAINDER,
925 help=
"ensure the cache, then run uv from an authenticated snapshot",
927 mode.add_argument(
"--selftest", action=
"store_true", help=
"run offline fail-closed tests")
928 parser.add_argument(
"--manifest", type=Path, default=DEFAULT_MANIFEST)
929 parser.add_argument(
"--cache-root", type=Path, default=DEFAULT_CACHE)
930 return parser.parse_args()
934 """Dispatch the requested bootstrap mode."""
939 elif args.run
is not None:
940 status = run_cached_uv(args.manifest, args.cache_root, args.run, ensure=
False)
941 elif args.ensure_and_run
is not None:
942 status = run_cached_uv(args.manifest, args.cache_root, args.ensure_and_run, ensure=
True)
944 manifest = load_manifest(args.manifest)
945 _, asset_name, _ = select_asset(manifest)
946 version = manifest[
"version"]
947 if not isinstance(version, str):
948 fail(
"uv manifest version is not a string")
949 destination = cache_destination(args.cache_root, version, asset_name)
952 elif args.check_cache_modes:
953 verify_cached_modes(destination.parent / asset_name, destination)
955 elif args.verify_cache:
956 print(verify_cached_uv(args.manifest, args.cache_root))
958 print(ensure_uv(args.manifest, args.cache_root))
963if __name__ ==
"__main__":
965 raise SystemExit(
main())
966 except CacheApplyRequiredError
as error:
967 print(f
"APPLY REQUIRED: {error}", file=sys.stderr)
968 raise SystemExit(2)
from error
969 except BootstrapError
as error:
970 print(f
"ERROR: {error}", file=sys.stderr)
971 raise SystemExit(1)
from error
void main(void)
The application entry point Reset_Handler hands control to.