feat: bootstrap NAS music deduper
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
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()
|
||||
Reference in New Issue
Block a user