forked from pex-tool/pex
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
253 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
# Copyright 2024 Pex project contributors. | ||
# Licensed under the Apache License, Version 2.0 (see LICENSE). | ||
|
||
from __future__ import absolute_import | ||
|
||
import os.path | ||
import sqlite3 | ||
from contextlib import contextmanager | ||
from typing import Union | ||
|
||
from pex.atomic_directory import atomic_directory | ||
from pex.cache.dirs import VenvDir | ||
from pex.common import CopyMode | ||
from pex.dist_metadata import ProjectNameAndVersion | ||
from pex.typing import TYPE_CHECKING | ||
from pex.variables import ENV | ||
|
||
if TYPE_CHECKING: | ||
from typing import Iterator, List, Tuple | ||
|
||
from pex.pex_info import PexInfo | ||
|
||
|
||
_SCHEMA = """ | ||
PRAGMA journal_mode=WAL; | ||
CREATE TABLE wheels ( | ||
name TEXT NOT NULL, | ||
hash TEXT NOT NULL, | ||
project_name TEXT NOT NULL, | ||
version TEXT NOT NULL, | ||
PRIMARY KEY (name ASC, hash ASC) | ||
) WITHOUT ROWID; | ||
CREATE UNIQUE INDEX wheels_idx_hash ON wheels (hash ASC); | ||
CREATE INDEX wheels_idx_project_name ON wheels (project_name ASC); | ||
CREATE INDEX wheels_idx_version ON wheels (version ASC); | ||
CREATE TABLE zipapps ( | ||
pex_hash TEXT PRIMARY KEY ASC, | ||
bootstrap_hash TEXT NOT NULL, | ||
code_hash TEXT NOT NULL | ||
) WITHOUT ROWID; | ||
CREATE INDEX zipapps_idx_bootstrap_hash ON zipapps (bootstrap_hash ASC); | ||
CREATE INDEX zipapps_idx_code_hash ON zipapps (code_hash ASC); | ||
CREATE TABLE zipapp_deps ( | ||
pex_hash TEXT NOT NULL REFERENCES zipapps(pex_hash) ON DELETE CASCADE, | ||
wheel_hash TEXT NOT NULL REFERENCES wheels(hash) ON DELETE CASCADE | ||
); | ||
CREATE INDEX zipapp_deps_idx_pex_hash ON zipapp_deps (pex_hash ASC); | ||
CREATE INDEX zipapp_deps_idx_wheel_hash ON zipapp_deps (wheel_hash ASC); | ||
CREATE TABLE venvs ( | ||
short_hash TEXT PRIMARY KEY ASC, | ||
pex_hash TEXT NOT NULL, | ||
contents_hash TEXT NOT NULL | ||
) WITHOUT ROWID; | ||
CREATE INDEX venvs_idx_pex_hash ON venvs (pex_hash ASC); | ||
CREATE TABLE venv_deps ( | ||
venv_hash TEXT NOT NULL REFERENCES venvs(short_hash) ON DELETE CASCADE, | ||
wheel_hash TEXT NOT NULL REFERENCES wheels(hash) ON DELETE CASCADE | ||
); | ||
CREATE INDEX venv_deps_idx_venv_hash ON venv_deps (venv_hash ASC); | ||
CREATE INDEX venv_deps_idx_wheel_hash ON venv_deps (wheel_hash ASC); | ||
""" | ||
|
||
|
||
@contextmanager | ||
def db_connection(): | ||
# type: () -> Iterator[sqlite3.Connection] | ||
db_dir = os.path.join(ENV.PEX_ROOT, "data") | ||
with atomic_directory(db_dir) as atomic_dir: | ||
if not atomic_dir.is_finalized(): | ||
with sqlite3.connect(os.path.join(atomic_dir.work_dir, "cache.db")) as conn: | ||
conn.executescript(_SCHEMA).close() | ||
with sqlite3.connect(os.path.join(db_dir, "cache.db")) as conn: | ||
conn.executescript( | ||
""" | ||
PRAGMA synchronous=NORMAL; | ||
PRAGMA foreign_keys=ON; | ||
""" | ||
).close() | ||
yield conn | ||
|
||
|
||
@contextmanager | ||
def _inserted_wheels(pex_info): | ||
# type: (PexInfo) -> Iterator[sqlite3.Cursor] | ||
|
||
wheels = [] # type: List[Tuple[str, str, str, str]] | ||
for wheel_name, wheel_hash in pex_info.distributions.items(): | ||
pnav = ProjectNameAndVersion.from_filename(wheel_name) | ||
wheels.append( | ||
( | ||
wheel_name, | ||
wheel_hash, | ||
str(pnav.canonicalized_project_name), | ||
str(pnav.canonicalized_version), | ||
) | ||
) | ||
|
||
with db_connection() as conn: | ||
cursor = conn.executemany( | ||
""" | ||
INSERT OR IGNORE INTO wheels ( | ||
name, | ||
hash, | ||
project_name, | ||
version | ||
) VALUES (?, ?, ?, ?) | ||
""", | ||
wheels, | ||
) | ||
yield cursor | ||
cursor.close() | ||
|
||
|
||
def record_zipapp_dependencies(pex_info): | ||
# type: (PexInfo) -> None | ||
|
||
with _inserted_wheels(pex_info) as cursor: | ||
cursor.execute( | ||
""" | ||
INSERT OR IGNORE INTO zipapps ( | ||
pex_hash, | ||
code_hash, | ||
bootstrap_hash | ||
) VALUES (?, ?, ?) | ||
""", | ||
(pex_info.pex_hash, pex_info.bootstrap_hash, pex_info.code_hash), | ||
).executemany( | ||
""" | ||
INSERT OR IGNORE INTO zipapp_deps ( | ||
pex_hash, | ||
wheel_hash | ||
) VALUES (?, ?) | ||
""", | ||
tuple( | ||
(pex_info.pex_hash, wheel_hash) for wheel_hash in pex_info.distributions.values() | ||
), | ||
).close() | ||
|
||
|
||
def record_zipapp_access(unzip_dir): | ||
# type: (...) -> None | ||
os.utime(unzip_dir, None) | ||
|
||
|
||
def record_venv_dependencies( | ||
copy_mode, # type: CopyMode.Value | ||
pex_info, # type: PexInfo | ||
venv_dir, # type: VenvDir | ||
venv_hash, # type: str | ||
): | ||
# type: (...) -> None | ||
|
||
def record_venv(coon_or_cursor): | ||
# type: (Union[sqlite3.Connection, sqlite3.Cursor]) -> sqlite3.Cursor | ||
return coon_or_cursor.execute( | ||
""" | ||
INSERT OR IGNORE INTO venvs ( | ||
short_hash, | ||
pex_hash, | ||
contents_hash | ||
) VALUES (?, ?, ?) | ||
""", | ||
(venv_hash, venv_dir.pex_hash, venv_dir.contents_hash), | ||
) | ||
|
||
if copy_mode is CopyMode.SYMLINK: | ||
with _inserted_wheels(pex_info) as cursor: | ||
record_venv(cursor).executemany( | ||
""" | ||
INSERT OR IGNORE INTO venv_deps ( | ||
venv_hash, | ||
wheel_hash | ||
) VALUES (?, ?) | ||
""", | ||
tuple((venv_hash, wheel_hash) for wheel_hash in pex_info.distributions.values()), | ||
).close() | ||
else: | ||
with db_connection() as conn: | ||
record_venv(conn).close() | ||
|
||
|
||
def record_venv_access(venv_dir): | ||
# type: (VenvDir) -> None | ||
os.utime(venv_dir.path, None) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters