export function parseApplyPatch()

in codex-cli/src/utils/agent/parse-apply-patch.ts [36:105]


export function parseApplyPatch(patch: string): Array<ApplyPatchOp> | null {
  if (!patch.startsWith(PATCH_PREFIX)) {
    // Patch must begin with '*** Begin Patch'
    return null;
  } else if (!patch.endsWith(PATCH_SUFFIX)) {
    // Patch must end with '*** End Patch'
    return null;
  }

  const patchBody = patch.slice(
    PATCH_PREFIX.length,
    patch.length - PATCH_SUFFIX.length,
  );

  const lines = patchBody.split("\n");

  const ops: Array<ApplyPatchOp> = [];

  for (const line of lines) {
    if (line.startsWith(END_OF_FILE_PREFIX)) {
      continue;
    } else if (line.startsWith(ADD_FILE_PREFIX)) {
      ops.push({
        type: "create",
        path: line.slice(ADD_FILE_PREFIX.length).trim(),
        content: "",
      });
      continue;
    } else if (line.startsWith(DELETE_FILE_PREFIX)) {
      ops.push({
        type: "delete",
        path: line.slice(DELETE_FILE_PREFIX.length).trim(),
      });
      continue;
    } else if (line.startsWith(UPDATE_FILE_PREFIX)) {
      ops.push({
        type: "update",
        path: line.slice(UPDATE_FILE_PREFIX.length).trim(),
        update: "",
        added: 0,
        deleted: 0,
      });
      continue;
    }

    const lastOp = ops[ops.length - 1];

    if (lastOp?.type === "create") {
      lastOp.content = appendLine(
        lastOp.content,
        line.slice(HUNK_ADD_LINE_PREFIX.length),
      );
      continue;
    }

    if (lastOp?.type !== "update") {
      // Expected update op but got ${lastOp?.type} for line ${line}
      return null;
    }

    if (line.startsWith(HUNK_ADD_LINE_PREFIX)) {
      lastOp.added += 1;
    } else if (line.startsWith("-")) {
      lastOp.deleted += 1;
    }
    lastOp.update += lastOp.update ? "\n" + line : line;
  }

  return ops;
}