diff --git a/packages/coding-agent/src/commit/agentic/tools/split-commit.ts b/packages/coding-agent/src/commit/agentic/tools/split-commit.ts index 43985d0c6..137dde24a 100644 --- a/packages/coding-agent/src/commit/agentic/tools/split-commit.ts +++ b/packages/coding-agent/src/commit/agentic/tools/split-commit.ts @@ -68,6 +68,7 @@ export function createSplitCommitTool( const errors: string[] = []; const warnings: string[] = []; const diffText = await git.diff(cwd, { cached: true }); + const validateHunksForDiff = git.createHunkSelectionValidator(diffText); const commits: SplitCommitGroup[] = params.commits.map((commit, index) => { const scope = commit.scope?.trim() || null; @@ -102,7 +103,7 @@ export function createSplitCommitTool( } warnings.push(...summaryValidation.warnings.map(warning => `Commit ${index + 1}: ${warning}`)); warnings.push(...typeValidation.warnings.map(warning => `Commit ${index + 1}: ${warning}`)); - const hunkValidation = validateHunkSelectors(index, changes, files, diffText); + const hunkValidation = validateHunkSelectors(index, changes, files, validateHunksForDiff); warnings.push(...hunkValidation.warnings); errors.push(...hunkValidation.errors); errors.push(...validateDependencies(index, dependencies, params.commits.length)); @@ -186,7 +187,7 @@ function validateHunkSelectors( commitIndex: number, changes: SplitCommitGroup["changes"], files: string[], - diffText: string, + validateHunksForDiff: (changes: SplitCommitGroup["changes"]) => git.HunkSelectionValidationError[], ): { errors: string[]; warnings: string[] } { const errors: string[] = []; const warnings: string[] = []; @@ -217,7 +218,7 @@ function validateHunkSelectors( } } if (errors.length === 0) { - for (const error of git.validateHunkSelections(diffText, changes)) { + for (const error of validateHunksForDiff(changes)) { errors.push(`${prefix}: ${error.message}`); } } diff --git a/packages/coding-agent/src/utils/git.ts b/packages/coding-agent/src/utils/git.ts index cea9f4f86..31779e5ed 100644 --- a/packages/coding-agent/src/utils/git.ts +++ b/packages/coding-agent/src/utils/git.ts @@ -682,12 +682,17 @@ function selectHunks(file: FileHunks, selector: HunkSelection["hunks"]): FileHun return file.hunks; } -export function validateHunkSelections( +export function createHunkSelectionValidator( rawDiff: string, +): (selections: readonly HunkSelection[]) => HunkSelectionValidationError[] { + const fileDiffMap = new Map(parseFileDiffs(rawDiff).map(entry => [entry.filename, entry])); + return selections => validateHunkSelectionsFromMap(fileDiffMap, selections); +} + +function validateHunkSelectionsFromMap( + fileDiffMap: ReadonlyMap, selections: readonly HunkSelection[], ): HunkSelectionValidationError[] { - const fileDiffs = parseFileDiffs(rawDiff); - const fileDiffMap = new Map(fileDiffs.map(entry => [entry.filename, entry])); const errors: HunkSelectionValidationError[] = []; for (const selection of selections) { @@ -707,6 +712,13 @@ export function validateHunkSelections( return errors; } +export function validateHunkSelections( + rawDiff: string, + selections: readonly HunkSelection[], +): HunkSelectionValidationError[] { + return createHunkSelectionValidator(rawDiff)(selections); +} + function parseStatusPorcelain(text: string): GitStatusSummary { let staged = 0; let unstaged = 0;