/* * aegis - project change supervisor * Copyright (C) 2001 Peter Miller; * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * * MANIFEST: functions to manipulate applys */ #include #include #include #include void patch_apply(pp, ifn, ofn) patch_ty *pp; string_ty *ifn; string_ty *ofn; { input_ty *ifp; output_ty *ofp; size_t j, k; int curline; trace(("patch_apply(pp = %08lX, ifn = \"%s\", ofn = \"%s\")\n{\n", (long)pp, (ifn ? ifn->str_text : ""), (ofn ? ofn->str_text : ""))); ofp = output_file_text_open(ofn); if (!ifn) { /* * Write all the lines from all the hunks * to the output file. * * (There will only be more than one hunk if * the patch asks for a modification to a file * which doesn't exist.) */ trace(("mark\n")); for (k = 0; k < pp->actions.length; ++k) { patch_hunk_ty *php; patch_line_list_ty *pllp; size_t m; php = pp->actions.item[0]; pllp = &php->after; for (m = 0; m < pllp->length; ++m) { output_put_str(ofp, pllp->item[m].value); output_fputc(ofp, '\n'); } } } else { string_list_ty buffer; /* * Read the file into an array. */ trace(("mark\n")); string_list_constructor(&buffer); ifp = input_file_text_open(ifn); for (;;) { string_ty *s; s = input_one_line(ifp); if (!s) break; string_list_append(&buffer, s); } input_delete(ifp); ifp = 0; /* * Now work over the hunk list, looking for where they go. */ trace(("mark\n")); for (j = 0; j < pp->actions.length; ++j) { int found; patch_hunk_ty *php; php = pp->actions.item[j]; trace(("looking for %d,%d\n", php->before.start_line_number, php->before.start_line_number + php->before.length - 1 )); found = 0; for (k = 1; k <= 11; ++k) { size_t m; int idx; int offset; /* * 0, -1, 1, -2, 2, etc... */ offset = k >> 1; if (k & 1) offset = -offset; /* * If it doesn't fit in the buffer, * it can't be there. */ idx = php->before.start_line_number - 1 + offset; if (idx < 0) continue; if (idx + php->before.length > buffer.nstrings) continue; /* * See if the lines match. */ for (m = 0; m < php->before.length; ++m) { if ( !str_equal ( buffer.string[idx + m], php->before.item[m].value ) ) break; } if (m >= php->before.length) { trace(("found, offset=%d\n", offset)); php->before.start_line_number += offset; found = 1; break; } } /* What should we do if it isn't found? */ } /* * Go over each hunk, emitting lines as we go. */ trace(("mark\n")); curline = 1; for (j = 0; j < pp->actions.length; ++j) { patch_hunk_ty *php; /* * First, any prelude. */ php = pp->actions.item[j]; while (curline < php->before.start_line_number) { output_put_str(ofp, buffer.string[curline - 1]); output_fputc(ofp, '\n'); ++curline; } curline += php->before.length; /* * Toss the "before" and emit the "after". * We checked that it was there already. */ for (k = 0; k < php->after.length; ++k) { output_put_str(ofp, php->after.item[k].value); output_fputc(ofp, '\n'); } } /* * Emit anything left over. */ trace(("mark\n")); while (curline <= buffer.nstrings) { output_put_str(ofp, buffer.string[curline - 1]); output_fputc(ofp, '\n'); ++curline; } } output_delete(ofp); trace(("}\n")); }