({
filePath,
fileContents,
edits,
}: {
filePath: string
fileContents: string
edits: FileEdit[]
})
| 260 | * NOTE: The returned patch is to be used for display purposes only - it has spaces instead of tabs |
| 261 | */ |
| 262 | export function getPatchForEdits({ |
| 263 | filePath, |
| 264 | fileContents, |
| 265 | edits, |
| 266 | }: { |
| 267 | filePath: string |
| 268 | fileContents: string |
| 269 | edits: FileEdit[] |
| 270 | }): { patch: StructuredPatchHunk[]; updatedFile: string } { |
| 271 | let updatedFile = fileContents |
| 272 | const appliedNewStrings: string[] = [] |
| 273 | |
| 274 | // Special case for empty files. |
| 275 | if ( |
| 276 | !fileContents && |
| 277 | edits.length === 1 && |
| 278 | edits[0] && |
| 279 | edits[0].old_string === '' && |
| 280 | edits[0].new_string === '' |
| 281 | ) { |
| 282 | const patch = getPatchForDisplay({ |
| 283 | filePath, |
| 284 | fileContents, |
| 285 | edits: [ |
| 286 | { |
| 287 | old_string: fileContents, |
| 288 | new_string: updatedFile, |
| 289 | replace_all: false, |
| 290 | }, |
| 291 | ], |
| 292 | }) |
| 293 | return { patch, updatedFile: '' } |
| 294 | } |
| 295 | |
| 296 | // Apply each edit and check if it actually changes the file |
| 297 | for (const edit of edits) { |
| 298 | // Strip trailing newlines from old_string before checking |
| 299 | const oldStringToCheck = edit.old_string.replace(/\n+$/, '') |
| 300 | |
| 301 | // Check if old_string is a substring of any previously applied new_string |
| 302 | for (const previousNewString of appliedNewStrings) { |
| 303 | if ( |
| 304 | oldStringToCheck !== '' && |
| 305 | previousNewString.includes(oldStringToCheck) |
| 306 | ) { |
| 307 | throw new Error( |
| 308 | 'Cannot edit file: old_string is a substring of a new_string from a previous edit.', |
| 309 | ) |
| 310 | } |
| 311 | } |
| 312 | |
| 313 | const previousContent = updatedFile |
| 314 | updatedFile = |
| 315 | edit.old_string === '' |
| 316 | ? edit.new_string |
| 317 | : applyEditToFile( |
| 318 | updatedFile, |
| 319 | edit.old_string, |
no test coverage detected