Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | 16x 16x 16x 8633x 159860x 8633x 16x 12864x 12864x 16x 6431x 6431x 6431x 6431x 16x 1005x 1005x 1005x 1758x 1758x 4671x 1758x 1758x 1758x 1758x 13992x 10702x 10702x 13992x 3290x 3290x 10702x 7602x 7602x 13992x 1758x 1758x 4542x 1005x | import * as lines from '../../lines';
import {diffKeys} from '../hunks';
import {type Hunk, HUNK_OP_TYPE} from '../types';
/** Serializers yield chunks; tests compare whole documents. */
export const text = (chunks: Iterable<string>): string => {
let out = '';
for (const chunk of chunks) out += chunk;
return out;
};
/**
* A file, as a command reads one: lines without terminators plus whether the
* last one is terminated. `'a\nb'` is two lines, the second unterminated.
*/
export class File {
public readonly lines: string[];
public readonly noEol: boolean;
constructor(content: string) {
this.noEol = content !== '' && !content.endsWith('\n');
this.lines = content === '' ? [] : (this.noEol ? content : content.slice(0, -1)).split('\n');
}
}
/** The whole pipeline a `diff` command runs, up to the writers. */
export const diff = (a: string, b: string) => {
const src = new File(a);
const dst = new File(b);
const patch = lines.diff(diffKeys(src.lines, src.noEol), diffKeys(dst.lines, dst.noEol));
return {
src: src.lines,
dst: dst.lines,
patch,
opts: {srcNoEol: src.noEol, dstNoEol: dst.noEol},
};
};
/**
* Replays hunks against `src`, checking every line number and context line on
* the way. A hunk set can be plausible in every printed column and still be
* unapplicable; this is the property that catches it.
*/
export const replay = (src: string[], hunks: Hunk[]): string[] => {
const out: string[] = [];
let si = 0;
for (const hunk of hunks) {
const start = hunk.oldCount ? hunk.oldStart - 1 : hunk.oldStart;
expect(start).toBeGreaterThanOrEqual(si);
while (si < start) out.push(src[si++]);
expect(hunk.newStart).toBe(hunk.newCount ? out.length + 1 : out.length);
let oldSeen = 0;
let newSeen = 0;
for (const line of hunk.lines) {
if (line.op !== HUNK_OP_TYPE.INS) {
expect(src[si]).toBe(line.text);
oldSeen++;
}
if (line.op === HUNK_OP_TYPE.INS) {
out.push(line.text);
newSeen++;
} else if (line.op === HUNK_OP_TYPE.EQL) {
out.push(src[si]);
newSeen++;
}
if (line.op !== HUNK_OP_TYPE.INS) si++;
}
expect(oldSeen).toBe(hunk.oldCount);
expect(newSeen).toBe(hunk.newCount);
}
while (si < src.length) out.push(src[si++]);
return out;
};
|