# apps/server/src/checkpointing/Diffs.ts · gitcafe/t3code

[View on GitCafe](https://git.cafe/gitcafe/t3code/blob/bc03c3640d6d3bb44e5fb477bfd78d7484cd0e00/apps/server/src/checkpointing/Diffs.ts)

Repository: [gitcafe/t3code](https://git.cafe/gitcafe/t3code)

Visibility: public

Requested revision: bc03c3640d6d3bb44e5fb477bfd78d7484cd0e00

Requested commit: bc03c3640d6d3bb44e5fb477bfd78d7484cd0e00

Commit: bc03c3640d6d3bb44e5fb477bfd78d7484cd0e00

Blob: b7951009118e912e51b68982aba41272f3dfb5d8

Size: 1068 bytes

[Immutable source](https://git.cafe/gitcafe/t3code/blob/bc03c3640d6d3bb44e5fb477bfd78d7484cd0e00/apps/server/src/checkpointing/Diffs.ts?format=markdown)

```
export interface TurnDiffFileSummary {
  readonly path: string;
  readonly additions: number;
  readonly deletions: number;
}

/** Reads Git's NUL-delimited numstat output without decoding display paths. */
export function parseTurnDiffFilesFromNumstat(numstat: string): ReadonlyArray<TurnDiffFileSummary> {
  const records = numstat.split("\0");
  const files: TurnDiffFileSummary[] = [];

  for (let index = 0; index < records.length; index += 1) {
    const record = records[index]!;
    const counts = /^(\d+|-)\t(\d+|-)\t/.exec(record);
    if (!counts) continue;

    let path = record.slice(counts[0].length);
    if (path.length === 0) {
      // Renames and copies use two more records: the source and destination.
      path = records[index + 2] ?? "";
      index += 2;
    }
    if (path.length === 0) continue;

    files.push({
      path,
      additions: counts[1] === "-" ? 0 : Number(counts[1]),
      deletions: counts[2] === "-" ? 0 : Number(counts[2]),
    });
  }

  return files.toSorted((left, right) => left.path.localeCompare(right.path));
}

```
