import { open } from "fs/promises"; /** * get hash of file or directory. * * Contains a hashing method that matches the hashing method described * here: [https://pypi.org/project/oshash/](https://pypi.org/project/oshash/) * This hashing method is particularly useful when you don't want to read * an entire file's bytes to generate a hash, provided you trust that any * changes to the file will cause byte differences in the first and last * bytes of the file, or a change to its file size. */ export async function oshash( path: string, ){ const chunkSize = 4096; const minFileSize = chunkSize * 2; const fd = await open(path, "r"); const st = await fd.stat(); let hash = BigInt(st.size); if (st.size < minFileSize){ throw new Error("File is too small to hash"); } // read first and last chunk const firstChunk = new Uint8Array(chunkSize); await fd.read(firstChunk, 0, chunkSize, 0); const lastChunk = new Uint8Array(chunkSize); await fd.read(lastChunk, 0, chunkSize, st.size - chunkSize); // iterate over first and last chunk. // for each uint64_t, add it to the hash. const firstChunkView = new DataView(firstChunk.buffer); for (let i = 0; i < chunkSize; i += 8){ hash += firstChunkView.getBigUint64(i, true); // prevent overflow hash = (hash & 0xFFFFFFFFFFFFFFFFn); } const lastChunkView = new DataView(lastChunk.buffer); for (let i = 0; i < chunkSize; i += 8){ hash += lastChunkView.getBigUint64(i, true); // prevent overflow hash = (hash & 0xFFFFFFFFFFFFFFFFn); } return hash; }