Something went wrong. Try again.
A simple DAV sync application / cli
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162import { createHash, type Hash } from "node:crypto";import { createReadStream } from "node:fs";import { open } from "node:fs/promises";import { HEAD_SIZE } from "./detect.ts";
/** Hashes a byte stream as it passes: the whole content, and its first HEAD_SIZE bytes. */export class ContentHasher { #full: Hash = createHash("sha256"); #head: Hash | null = createHash("sha256"); #headDigest: string | null = null; #seen = 0; size = 0;
update(chunk: Uint8Array): void { this.#full.update(chunk); this.size += chunk.byteLength; if (this.#head) { const take = Math.min(HEAD_SIZE - this.#seen, chunk.byteLength); this.#head.update(chunk.subarray(0, take)); this.#seen += take; if (this.#seen >= HEAD_SIZE) this.#headDigest = this.#finishHead(); } }
digest(): { sha256: string; head: string; size: number } { const head = this.#headDigest ?? this.#finishHead(); return { sha256: this.#full.digest("hex"), head, size: this.size }; }
#finishHead(): string { const digest = this.#head!.digest("hex"); this.#head = null; return digest; }}
export async function hashFile(path: string): Promise<{ sha256: string; head: string; size: number }> { const hasher = new ContentHasher(); for await (const chunk of createReadStream(path)) hasher.update(chunk as Buffer); return hasher.digest();}
export async function headOfFile(path: string): Promise<string> { const handle = await open(path, "r"); try { const buffer = Buffer.alloc(HEAD_SIZE); let filled = 0; while (filled < HEAD_SIZE) { const { bytesRead } = await handle.read(buffer, filled, HEAD_SIZE - filled, filled); if (bytesRead === 0) break; filled += bytesRead; } return createHash("sha256").update(buffer.subarray(0, filled)).digest("hex"); } finally { await handle.close(); }}
export function headOfBytes(bytes: Uint8Array): string { return createHash("sha256").update(bytes.subarray(0, HEAD_SIZE)).digest("hex");}