You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2010/03/03 15:28:38 UTC
svn commit: r918486 - /subversion/trunk/subversion/libsvn_client/patch.c
Author: stsp
Date: Wed Mar 3 14:28:37 2010
New Revision: 918486
URL: http://svn.apache.org/viewvc?rev=918486&view=rev
Log:
Fix various bugs in file seeking and EOF handling in 'svn patch'.
* subversion/libsvn_client/patch.c
(read_line): Don't increment the current line counter past EOF.
(seek_to_line): Don't attempt to seek past EOF, fixing an endless loop.
If the EOF indicator was set before seeking backwards, clear it.
(match_hunk, scan_for_match, get_hunk_info): Don't clear EOF indicator,
seek_to_line() does this now. And don't seek past EOF.
(apply_hunk): If seeking past the hunk's original length fails,
reject the hunk. Note that since the hunk was already matched
successfully, this failure is unlikely.
Add a ### comment about an unrelated bug discovered recently.
Modified:
subversion/trunk/subversion/libsvn_client/patch.c
Modified: subversion/trunk/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/patch.c?rev=918486&r1=918485&r2=918486&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/patch.c (original)
+++ subversion/trunk/subversion/libsvn_client/patch.c Wed Mar 3 14:28:37 2010
@@ -529,7 +529,8 @@
target->eol_str, FALSE,
target->keywords, FALSE,
result_pool));
- target->current_line++;
+ if (! target->eof)
+ target->current_line++;
return SVN_NO_ERROR;
}
@@ -542,11 +543,17 @@
seek_to_line(patch_target_t *target, svn_linenum_t line,
apr_pool_t *scratch_pool)
{
+ svn_linenum_t saved_line;
+ svn_boolean_t saved_eof;
+
SVN_ERR_ASSERT(line > 0);
if (line == target->current_line)
return SVN_NO_ERROR;
+ saved_line = target->current_line;
+ saved_eof = target->eof;
+
if (line <= target->lines->nelts)
{
svn_stream_mark_t *mark;
@@ -560,7 +567,7 @@
const char *dummy;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- while (target->current_line < line)
+ while (! target->eof && target->current_line < line)
{
svn_pool_clear(iterpool);
SVN_ERR(read_line(target, &dummy, iterpool, iterpool));
@@ -568,6 +575,10 @@
svn_pool_destroy(iterpool);
}
+ /* After seeking backwards from EOF position clear EOF indicator. */
+ if (saved_eof && saved_line > target->current_line)
+ target->eof = FALSE;
+
return SVN_NO_ERROR;
}
@@ -644,7 +655,6 @@
*matched = FALSE;
}
SVN_ERR(seek_to_line(target, saved_line, iterpool));
- target->eof = FALSE;
svn_pool_destroy(iterpool);
@@ -705,7 +715,8 @@
}
}
- SVN_ERR(seek_to_line(target, target->current_line + 1, iterpool));
+ if (! target->eof)
+ SVN_ERR(seek_to_line(target, target->current_line + 1, iterpool));
}
svn_pool_destroy(iterpool);
@@ -740,13 +751,19 @@
else if (hunk->original_start > 0 && target->kind == svn_node_file)
{
svn_linenum_t saved_line = target->current_line;
- svn_boolean_t saved_eof = target->eof;
/* Scan for a match at the line where the hunk thinks it
* should be going. */
SVN_ERR(seek_to_line(target, hunk->original_start, scratch_pool));
- SVN_ERR(scan_for_match(&matched_line, target, hunk, TRUE,
- hunk->original_start + 1, fuzz, scratch_pool));
+ if (target->current_line != hunk->original_start)
+ {
+ /* Seek failed. */
+ matched_line = 0;
+ }
+ else
+ SVN_ERR(scan_for_match(&matched_line, target, hunk, TRUE,
+ hunk->original_start + 1, fuzz, scratch_pool));
+
if (matched_line != hunk->original_start)
{
/* Scan the whole file again from the start. */
@@ -769,7 +786,6 @@
}
SVN_ERR(seek_to_line(target, saved_line, scratch_pool));
- target->eof = saved_eof;
}
else
{
@@ -894,6 +910,8 @@
if (target->kind == svn_node_file)
{
+ svn_linenum_t line;
+
/* Move forward to the hunk's line, copying data as we go.
* Also copy leading lines of context which matched with fuzz.
* The target has changed on the fuzzy-matched lines,
@@ -903,9 +921,16 @@
/* Skip the target's version of the hunk.
* Don't skip trailing lines which matched with fuzz. */
- SVN_ERR(seek_to_line(target, target->current_line +
- hi->hunk->original_length - (2 * hi->fuzz),
- pool));
+ /* ### What if current line is part of hunk context? */
+ line = target->current_line + hi->hunk->original_length - (2 * hi->fuzz);
+ SVN_ERR(seek_to_line(target, line, pool));
+ if (target->current_line != line)
+ {
+ /* Seek failed, reject this hunk. */
+ hi->rejected = TRUE;
+ SVN_ERR(reject_hunk(target, hi, pool));
+ return SVN_NO_ERROR;
+ }
}
/* Write the hunk's version to the patched result.