mirror of
https://github.com/fromchat-messenger/web.git
synced 2026-09-22 19:15:08 +03:00
86 lines
2.3 KiB
Python
86 lines
2.3 KiB
Python
"""Small helpers: hashing, dedupe, cache keys."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
def sanitize_ref(ref: str) -> str:
|
|
s = ref.replace("/", "_").replace(":", "__").replace("@", "__at__")
|
|
return s
|
|
|
|
|
|
def dedupe_preserve(items: list[str]) -> list[str]:
|
|
seen: set[str] = set()
|
|
out: list[str] = []
|
|
for x in items:
|
|
if x not in seen:
|
|
seen.add(x)
|
|
out.append(x)
|
|
return out
|
|
|
|
|
|
def read_file_if_exists(path: Path) -> str:
|
|
if path.is_file():
|
|
return path.read_text(encoding="utf-8", errors="replace")
|
|
return ""
|
|
|
|
|
|
def local_image_layer_fp(image: str) -> str:
|
|
def inspect_layers(ref: str) -> subprocess.CompletedProcess[str]:
|
|
return subprocess.run(
|
|
["docker", "image", "inspect", "-f", "{{json .RootFS.Layers}}", ref],
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
|
|
p = inspect_layers(image)
|
|
if p.returncode != 0:
|
|
# Docker Desktop occasionally ends up in a state where repo:tag exists in `docker images`
|
|
# but `docker image inspect repo:tag` fails. Inspecting by content-addressed ID works.
|
|
id_p = subprocess.run(
|
|
["docker", "images", "--no-trunc", "--format", "{{.ID}}", image],
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
image_id = (id_p.stdout or "").strip()
|
|
if not image_id:
|
|
return ""
|
|
p = inspect_layers(image_id)
|
|
if p.returncode != 0:
|
|
return ""
|
|
|
|
return hashlib.sha256(p.stdout.encode()).hexdigest()
|
|
|
|
|
|
def compute_inputs_hash(
|
|
context: Path,
|
|
dockerfile: Path,
|
|
*,
|
|
hash_script: Path,
|
|
python_exe: str | None = None,
|
|
) -> str:
|
|
exe = python_exe or sys.executable
|
|
p = subprocess.run(
|
|
[exe, str(hash_script), "--context", str(context), "--dockerfile", str(dockerfile)],
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
if p.returncode != 0:
|
|
return ""
|
|
return p.stdout.strip()
|
|
|
|
|
|
def local_docker_image_tags() -> set[str]:
|
|
p = subprocess.run(
|
|
["docker", "images", "--format", "{{.Repository}}:{{.Tag}}"],
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
if p.returncode != 0:
|
|
return set()
|
|
return {line.strip() for line in p.stdout.splitlines() if line.strip()}
|