// // aegis - project change supervisor // Copyright (C) 2001-2006, 2008 Peter Miller // // 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 3 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, see // . // #include #include #include // assert #include #include #include #include #include #include #include #include static patch_format_ty *format[] = { &patch_format_context, &patch_format_uni, &patch_format_diff, }; patch_list_ty * patch_read(input &ip, int required) { patch_list_ty *result; patch_context_ty *context; trace(("patch_read()\n{\n")); context = patch_context_new(ip); result = patch_list_new(); string_list_ty 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", context->get_file_name().c_str())); 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. // garbage.push_back(s); patch_context_discard(context, 1); trace(("toss one line\n")); continue; } trace(("found header, type %s\n", fp->name)); assert(pp->name.nstrings); // // The first lot of "garbage" is kept as the change // description. // if (result->length == 0) { result->description = garbage.unsplit("\n"); } garbage.clear(); // // 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; trace(("got hunk\n")); 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 ( pp->name.nstrings && strstr(pp->name.string[0]->str_text, "test/") && strstr(pp->name.string[0]->str_text, ".sh") ) pp->usage = file_usage_test; } if (required && result->length == 0) ip->fatal_error("no patch found"); // // clean up and go home // patch_context_delete(context); trace(("return %08lX\n", (long)result)); trace(("}\n")); return result; }