spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

claude-code / mods / diff / hooks / git / parse / parse-numstat.ts
62 lines · 1.8 KBRaw
1import type Types from '../types'
2import { RENAME_RECORDS } from './rename-records'
3
4/**
5 * `git diff --numstat -z` output as totals over every row and the first
6 * rows up to the cap; a binary file (`-` counts) is a 0/0 row marked binary.
7 *
8 * A record is `<added>\t<removed>\t<path>` ended by NUL, the path raw; a
9 * rename is `<added>\t<removed>\t` then the old and the new path as the
10 * next two records, kept as one row under the new path.
11 *
12 * @param stdout the command's standard output
13 * @param maxFiles how many rows to keep
14 * @returns the totals and the kept rows
15 */
16export function parseNumstat(
17 stdout: string,
18 maxFiles: number,
19): Types.NumstatResult {
20 const files: Types.FileStat[] = []
21 const stats = { filesCount: 0, linesAdded: 0, linesRemoved: 0 }
22 const records = stdout.split('\0')
23 let at = 0
24
25 while (at < records.length) {
26 const [addedField, removedField, ...pathFields] = (records[at] ?? '').split(
27 '\t',
28 )
29 const inline = pathFields.join('\t')
30 const isRename = pathFields.length === 1 && inline === ''
31 const renamedFrom = isRename ? (records[at + 1] ?? null) : null
32 const path = isRename ? (records[at + 2] ?? '') : inline
33 at += isRename ? RENAME_RECORDS : 1
34 const isRow =
35 addedField !== undefined && removedField !== undefined && path !== ''
36
37 if (!isRow) {
38 continue
39 }
40
41 const isBinary = addedField === '-' || removedField === '-'
42 const added = isBinary ? 0 : Number(addedField) || 0
43 const removed = isBinary ? 0 : Number(removedField) || 0
44 stats.filesCount += 1
45 stats.linesAdded += added
46 stats.linesRemoved += removed
47
48 if (files.length < maxFiles) {
49 files.push({
50 path,
51 renamedFrom,
52 added,
53 removed,
54 isBinary,
55 isUntracked: false,
56 isPreSession: false,
57 })
58 }
59 }
60
61 return { stats, files }
62}