Chore: embed content hash

This commit is contained in:
SukkaW
2026-08-01 01:30:47 +08:00
parent 32a0c1a49b
commit b3bcec6de6
6 changed files with 131 additions and 41 deletions

View File

@@ -7,27 +7,41 @@ import { readFileByLine } from './fetch-text-by-line';
import { writeFile } from './misc';
import { createCompareSource, fileEqualWithCommentComparator } from 'foxts/compare-source';
import { promisify } from 'node:util';
import { extractContentHashFromFile } from './content-hash';
const fileEqual = createCompareSource(fileEqualWithCommentComparator);
/**
* To keep metadata comment `last updated` not change if real content is the same,
* we compare real content lines and only write if actual content is different,
* and the new `last updated` will be written along with new content.
* we only write when the actual content differs, and the new `last updated` will
* be written along with new content.
*
* When `contentHash` is provided (and the previous output already embeds a
* content hash marker), the comparison only reads the first chunk of the
* previous file. Otherwise it falls back to a full comment-insensitive
* line-by-line comparison.
*/
export async function compareAndWriteFile(span: Span, linesA: string[], filePath: string) {
export async function compareAndWriteFile(span: Span, linesA: string[], filePath: string, contentHash: string | null = null) {
// readFileByLine will not include last empty line. So we always pop the linesA for comparison purpose
if (linesA.length > 0 && linesA[linesA.length - 1] === '') {
linesA.pop();
}
const isEqual = await span.traceChildAsync(`compare ${filePath}`, async () => {
if (fs.existsSync(filePath)) {
return fileEqual(linesA, readFileByLine(filePath));
if (!fs.existsSync(filePath)) {
console.log(`${filePath} does not exists, writing...`);
return false;
}
console.log(`${filePath} does not exists, writing...`);
return false;
if (contentHash) {
const previousHash = await extractContentHashFromFile(filePath);
if (previousHash) {
return previousHash === contentHash;
}
// previous output predates the content hash marker, fall through to full comparison
}
return fileEqual(linesA, readFileByLine(filePath));
});
if (isEqual) {