/* * 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 reads */ #include #include #include /* assert */ #include #include #include #include #include #include #include #include static patch_format_ty *format[] = { &patch_format_context, &patch_format_uni, }; patch_list_ty * patch_read(input) input_ty *input; { patch_list_ty *result; patch_context_ty *context; string_list_ty garbage; trace(("patch_read(input = %08lX)\n{\n", (long)input)); context = patch_context_new(input); result = patch_list_new(); string_list_constructor(&garbage); for (;;) { patch_ty *pp; size_t j; patch_format_ty *fp; /* * Look for a patch header; * it could be in one of several formats. */ trace(("%s\n", input_name(context->input)->str_text)); pp = 0; fp = 0; for (j = 0; j < SIZEOF(format); ++j) { fp = format[j]; pp = fp->header(context); if (pp) break; fp = 0; } assert(!pp == !fp); /* * If there was no patch in there, we need to deal with * the garbage. */ if (!pp) { string_ty *s; s = patch_context_getline(context, 0); if (!s) break; /* * Stash the first line in the buffer, * and discard it from the context. */ string_list_append(&garbage, s); patch_context_discard(context, 1); trace(("toss one line\n")); continue; } trace(("found header, type %s\n", fp->name)); /* * The first lot of "garbage" is kept as the change * description. */ if (result->length == 0) { result->description = wl2str(&garbage, 0, garbage.nstrings, "\n"); } string_list_destructor(&garbage); /* * Found a patch header, read the rest of it. */ patch_list_append(result, pp); assert(fp); for (;;) { patch_hunk_ty *php; php = fp->hunk(context); if (!php) break; patch_append(pp, php); } /* * Figure what this patch is doing. */ pp->action = file_action_modify; if (pp->actions.length == 1) { patch_hunk_ty *php; php = pp->actions.item[0]; if ( php->after.length == 0 && php->after.start_line_number == 0 ) pp->action = file_action_remove; else if ( php->before.length == 0 && php->before.start_line_number == 0 ) pp->action = file_action_create; } /* * Figure what sort of file this is. * * (How do we know it's a test? It is entirely possible * that test names have been changed from the default.) */ pp->usage = file_usage_source; if ( strstr(pp->name.string[0]->str_text, "test/") && strstr(pp->name.string[0]->str_text, ".sh") ) pp->usage = file_usage_test; } if (result->length == 0) input_fatal_error(input, "no patch found"); /* * clean up and go home */ string_list_destructor(&garbage); patch_context_delete(context); trace(("return %08lX\n", (long)result)); trace(("}\n")); return result; }