/*
* 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"));
}