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 / fetch-hunks / fetch-hunks.ts
87 lines · 2.4 KBRaw
1import Limits from '../../limits'
2import Argv from '../argv'
3import { EMPTY_FILE_HUNKS } from '../empty-file-hunks'
4import Parse from '../parse'
5import type Types from '../types'
6import { isLastOfDiff } from './is-last-of-diff'
7import { withClosingLine } from './with-closing-line'
8
9/**
10 * The rows' hunks against the base their counts were read against, from one
11 * git child over their literal paths; each but the last, a closing empty row.
12 *
13 * A row with no body (untracked, binary, renamed, or staged then edited on
14 * an unborn HEAD) is never named to git. Paths past MAX_PATHSPEC_CHARS and
15 * files a cut answer left unread go to a further child.
16 *
17 * @param run runs git against the pinned repository
18 * @param data the fetch the rows belong to
19 * @param files the rows
20 * @returns each row's parsed body by path, null where git failed
21 */
22export async function fetchHunks(
23 run: Types.GitRun,
24 data: Types.DiffData,
25 files: readonly Types.FileStat[],
26): Promise<ReadonlyMap<string, Types.FileHunks | null>> {
27 const bodied = files.filter(
28 file =>
29 !file.isUntracked &&
30 !file.isBinary &&
31 file.renamedFrom === null &&
32 !data.stalePaths.includes(file.path),
33 )
34
35 const bodiless = files
36 .filter(file => !bodied.includes(file))
37 .map(file => [file.path, EMPTY_FILE_HUNKS] as const)
38
39 if (bodied.length === 0) {
40 return new Map(bodiless)
41 }
42
43 let spent = 0
44
45 const asked = bodied
46 .map(file => file.path)
47 .filter((path, at) => {
48 spent += path.length
49
50 return at === 0 || spent <= Limits.MAX_PATHSPEC_CHARS
51 })
52
53 const { exitCode, stdout } = await run([
54 '--literal-pathspecs',
55 ...Argv.DIFF_LEADING_ARGS,
56 ...Argv.HUNKS_ARGS,
57 data.baseRef,
58 '--',
59 ...asked,
60 ])
61
62 const hasAnswered = exitCode === 0
63
64 const settled = hasAnswered
65 ? Parse.parseFileDiffs(stdout, asked)
66 : new Map<string, Types.FileHunks>()
67
68 const waiting = bodied.filter(file => !settled.has(file.path))
69 const isStuck = settled.size === 0
70
71 const rest = isStuck
72 ? waiting.map(file => [file.path, null] as const)
73 : await fetchHunks(run, data, waiting)
74
75 return new Map<string, Types.FileHunks | null>([
76 ...bodiless,
77 ...bodied.flatMap(file => {
78 const body = settled.get(file.path)
79 const isLast = isLastOfDiff(data, file)
80
81 return body
82 ? [[file.path, isLast ? body : withClosingLine(body)] as const]
83 : []
84 }),
85 ...rest,
86 ])
87}