| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- import { asyncWriteToStream } from 'foxts/async-write-to-stream';
- import { fastStringArrayJoin } from 'foxts/fast-string-array-join';
- import fs from 'node:fs';
- import picocolors from 'picocolors';
- import type { Span } from '../trace';
- import { readFileByLine } from './fetch-text-by-line';
- import { writeFile } from './misc';
- import { createCompareSource, fileEqualWithCommentComparator } from 'foxts/compare-source';
- import { promisify } from 'node:util';
- export const fileEqual = createCompareSource(fileEqualWithCommentComparator);
- export async function compareAndWriteFile(span: Span, linesA: string[], filePath: string) {
- // 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));
- }
- console.log(`${filePath} does not exists, writing...`);
- return false;
- });
- if (isEqual) {
- console.log(picocolors.gray(picocolors.dim(`same content, bail out writing: ${filePath}`)));
- return;
- }
- return span.traceChildAsync<void>(`writing ${filePath}`, async () => {
- const linesALen = linesA.length;
- // The default highwater mark is normally 16384,
- // So we make sure direct write to file if the content is
- // most likely less than 250 lines
- if (linesALen < 250) {
- return writeFile(filePath, fastStringArrayJoin(linesA, '\n'));
- }
- const writeStream = fs.createWriteStream(filePath);
- let p;
- for (let i = 0; i < linesALen; i++) {
- p = asyncWriteToStream(writeStream, linesA[i] + '\n');
- // eslint-disable-next-line no-await-in-loop -- stream high water mark
- if (p) await p;
- }
- await new Promise<void>(resolve => {
- // Since we previously poped the last empty line for comparison, we need to add it back here to ensure final EOF line
- writeStream.end('\n', resolve);
- });
- await promisify(writeStream.close.bind(writeStream))();
- });
- }
|