| 242 | |
| 243 | // Apply patch functionality |
| 244 | export function maybeParseApplyPatch( |
| 245 | argv: string[], |
| 246 | ): |
| 247 | | { type: MaybeApplyPatch.Body; args: ApplyPatchArgs } |
| 248 | | { type: MaybeApplyPatch.PatchParseError; error: Error } |
| 249 | | { type: MaybeApplyPatch.NotApplyPatch } { |
| 250 | const APPLY_PATCH_COMMANDS = ["apply_patch", "applypatch"] |
| 251 | |
| 252 | // Direct invocation: apply_patch <patch> |
| 253 | if (argv.length === 2 && APPLY_PATCH_COMMANDS.includes(argv[0])) { |
| 254 | try { |
| 255 | const { hunks } = parsePatch(argv[1]) |
| 256 | return { |
| 257 | type: MaybeApplyPatch.Body, |
| 258 | args: { |
| 259 | patch: argv[1], |
| 260 | hunks, |
| 261 | }, |
| 262 | } |
| 263 | } catch (error) { |
| 264 | return { |
| 265 | type: MaybeApplyPatch.PatchParseError, |
| 266 | error: error as Error, |
| 267 | } |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | // Bash heredoc form: bash -lc 'apply_patch <<"EOF" ...' |
| 272 | if (argv.length === 3 && argv[0] === "bash" && argv[1] === "-lc") { |
| 273 | // Simple extraction - in real implementation would need proper bash parsing |
| 274 | const script = argv[2] |
| 275 | const heredocMatch = script.match(/apply_patch\s*<<['"](\w+)['"]\s*\n([\s\S]*?)\n\1/) |
| 276 | |
| 277 | if (heredocMatch) { |
| 278 | const patchContent = heredocMatch[2] |
| 279 | try { |
| 280 | const { hunks } = parsePatch(patchContent) |
| 281 | return { |
| 282 | type: MaybeApplyPatch.Body, |
| 283 | args: { |
| 284 | patch: patchContent, |
| 285 | hunks, |
| 286 | }, |
| 287 | } |
| 288 | } catch (error) { |
| 289 | return { |
| 290 | type: MaybeApplyPatch.PatchParseError, |
| 291 | error: error as Error, |
| 292 | } |
| 293 | } |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | return { type: MaybeApplyPatch.NotApplyPatch } |
| 298 | } |
| 299 | |
| 300 | // File content manipulation |
| 301 | interface ApplyPatchFileUpdate { |