35 lines
890 B
Python
35 lines
890 B
Python
from __future__ import annotations
|
|
|
|
import hashlib
|
|
from pathlib import Path
|
|
|
|
from .constants import FAST_HASH_CHUNK
|
|
|
|
|
|
def fast_hash(path: Path) -> str:
|
|
"""Hash size + first/last 64 KiB; used only as a candidate key."""
|
|
size = path.stat().st_size
|
|
with path.open("rb") as f:
|
|
head = f.read(FAST_HASH_CHUNK)
|
|
if size > FAST_HASH_CHUNK:
|
|
f.seek(max(0, size - FAST_HASH_CHUNK))
|
|
tail = f.read(FAST_HASH_CHUNK)
|
|
h = hashlib.sha256()
|
|
h.update(str(size).encode())
|
|
h.update(b"\0")
|
|
h.update(head)
|
|
h.update(b"\0")
|
|
h.update(tail)
|
|
return h.hexdigest()
|
|
|
|
|
|
def sha256(path: Path, chunk_size: int = 1024 * 1024) -> str:
|
|
h = hashlib.sha256()
|
|
with path.open("rb") as f:
|
|
while True:
|
|
chunk = f.read(chunk_size)
|
|
if not chunk:
|
|
break
|
|
h.update(chunk)
|
|
return h.hexdigest()
|