Hi Stefan! Do you think the attached patch looks reasonable, e.g. it does not interfer with the overall design of 'svn patch'? It's not fun to review a patch that touches on so many parts. Sorry 'bout that. Find below some specific questions.
The patch code consist of four steps: 1) match text in streams 2) apply text to target stream (or reject stream) 3) install tmp files by copying them to the target path 4) send notifications on what we've done. Question 1 ------------ text_info_t is the datatype that will be passed around in step 1 and 2. Is the name ok? I tried target_info_t first but it sounded too vague. On the other hand, the doc strings for scan_for_match() and friends will sound strange: Scan lines of TEXT_INFO for a match of the original text of HUNK... Question 2 -------------- In step 3, we're passing both patch_target_t and text_info_t as parameters to apply_hunk() and reject_hunk() since we might need target->path and target->had_rejects. Is it ok to pass both? [[[ Create text_info_t for storing text related parts of patch_target_t. This is a step towards handling properties in the patch code. The idea is that text_info_t should be able to describe any text, be it from a file or a property. But for now we're only dealing with texts from a file. * subversion/libsvn_client/patch.c (text_info_t): New. (patch_target_t): Fields related to the text have been moved to the field 'text_info' (init_patch_target): Initialize 'text_info'. (resolve_target_wc_file_info, (read_line, (seek_to_line, (match_hunk, (scan_for_match): Replace 'target->' with 'text_info->' for fields that have moved. (match_existing_file): Use 'target->text_info' for accessing the streams. We still need other fields from the target and text_info can only refer to text_info of the file in this case. (get_hunk_info): Add 'text_info' parameter. We still need target for match_existing_file(). (copy_lines_to_target): Add 'text_info' parameter. (reject_hunk, (apply_hunk): Add 'text_info' parameter. We still need target for marking a target as having rejects. (send_patch_notification): Uses text_info->hunks (apply_one_patch): Pass around target->text_info to the match and apply/reject functions. ]]] Thanks, Daniel
Index: subversion/libsvn_client/patch.c =================================================================== --- subversion/libsvn_client/patch.c (revision 964865) +++ subversion/libsvn_client/patch.c (arbetskopia) @@ -65,28 +65,7 @@ typedef struct hunk_info_t { int fuzz; } hunk_info_t; -typedef struct patch_target_t { - /* The patch being applied. */ - const svn_patch_t *patch; - - /* The target path as it appeared in the patch file, - * but in canonicalised form. */ - const char *canon_path_from_patchfile; - - /* The target path, relative to the working copy directory the - * patch is being applied to. A patch strip count applies to this - * and only this path. This is never NULL. */ - const char *local_relpath; - - /* The absolute path of the target on the filesystem. - * Any symlinks the path from the patch file may contain are resolved. - * Is not always known, so it may be NULL. */ - char *local_abspath; - - /* The target file, read-only, seekable. This is NULL in case the target - * file did not exist prior to patch application. */ - apr_file_t *file; - +typedef struct text_info_t { /* A stream to read lines form the target file. This is NULL in case * the target file did not exist prior to patch application. */ svn_stream_t *stream; @@ -98,16 +77,10 @@ typedef struct hunk_info_t { * so EOL transformation and keyword contraction is done transparently. */ svn_stream_t *patched; - /* Path to the temporary file underlying the result stream. */ - const char *patched_path; - /* The reject stream, write-only, not seekable. * Hunks that are rejected will be written to this stream. */ svn_stream_t *reject; - /* Path to the temporary file underlying the reject stream. */ - const char *reject_path; - /* The line last read from the target file. */ svn_linenum_t current_line; @@ -127,6 +100,44 @@ typedef struct hunk_info_t { /* An array containing hunk_info_t structures for hunks already matched. */ apr_array_header_t *hunks; + /* True if end-of-file was reached while reading from the target. */ + svn_boolean_t eof; + + /* The keywords of the target. */ + apr_hash_t *keywords; + + /* The pool the target_info is allocated in. */ + apr_pool_t *pool; +} text_info_t; + +typedef struct patch_target_t { + /* The patch being applied. */ + const svn_patch_t *patch; + + /* The target path as it appeared in the patch file, + * but in canonicalised form. */ + const char *canon_path_from_patchfile; + + /* The target path, relative to the working copy directory the + * patch is being applied to. A patch strip count applies to this + * and only this path. This is never NULL. */ + const char *local_relpath; + + /* The absolute path of the target on the filesystem. + * Any symlinks the path from the patch file may contain are resolved. + * Is not always known, so it may be NULL. */ + char *local_abspath; + + /* The target file, read-only, seekable. This is NULL in case the target + * file did not exist prior to patch application. */ + apr_file_t *file; + + /* Path to the temporary file underlying the result stream. */ + const char *patched_path; + + /* Path to the temporary file underlying the reject stream. */ + const char *reject_path; + /* The node kind of the target as found in WC-DB prior * to patch application. */ svn_node_kind_t db_kind; @@ -137,9 +148,6 @@ typedef struct hunk_info_t { /* True if the target was locally deleted prior to patching. */ svn_boolean_t locally_deleted; - /* True if end-of-file was reached while reading from the target. */ - svn_boolean_t eof; - /* True if the target had to be skipped for some reason. */ svn_boolean_t skipped; @@ -167,8 +175,8 @@ typedef struct hunk_info_t { /* True if the target has the executable bit set. */ svn_boolean_t executable; - /* The keywords of the target. */ - apr_hash_t *keywords; + /* All the information that is specifict to the content of the target. */ + text_info_t *text_info; /* The pool the target is allocated in. */ apr_pool_t *pool; @@ -254,7 +262,7 @@ resolve_target_wc_file_info(svn_wc_context_t *wc_c SVN_ERR(svn_wc__node_get_url(&url, wc_ctx, target->local_abspath, scratch_pool, scratch_pool)); - SVN_ERR(svn_subst_build_keywords2(&target->keywords, + SVN_ERR(svn_subst_build_keywords2(&target->text_info->keywords, keywords_val->data, rev_str, url, changed_date, author, result_pool)); @@ -264,8 +272,8 @@ resolve_target_wc_file_info(svn_wc_context_t *wc_c APR_HASH_KEY_STRING); if (eol_style_val) { - svn_subst_eol_style_from_value(&target->eol_style, - &target->eol_str, + svn_subst_eol_style_from_value(&target->text_info->eol_style, + &target->text_info->eol_str, eol_style_val->data); } @@ -421,16 +429,23 @@ init_patch_target(patch_target_t **patch_target, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { patch_target_t *target; + text_info_t *text_info; target = apr_pcalloc(result_pool, sizeof(*target)); + text_info = apr_pcalloc(result_pool, sizeof(*text_info)); + text_info->current_line = 1; + text_info->eol_style = svn_subst_eol_style_none; + text_info->lines = apr_array_make(result_pool, 0, + sizeof(svn_stream_mark_t *)); + text_info->hunks = apr_array_make(result_pool, 0, sizeof(hunk_info_t *)); + text_info->keywords = apr_hash_make(result_pool); + text_info->pool = result_pool; + + target->text_info = text_info; + /* All other fields are FALSE or NULL due to apr_pcalloc(). */ target->patch = patch; - target->current_line = 1; - target->eol_style = svn_subst_eol_style_none; - target->lines = apr_array_make(result_pool, 0, - sizeof(svn_stream_mark_t *)); - target->hunks = apr_array_make(result_pool, 0, sizeof(hunk_info_t *)); target->db_kind = svn_node_none; target->kind_on_disk = svn_node_none; target->pool = result_pool; @@ -453,8 +468,8 @@ init_patch_target(patch_target_t **patch_target, APR_OS_DEFAULT, result_pool)); /* Create a stream to read from the target. */ - target->stream = svn_stream_from_aprfile2(target->file, - FALSE, result_pool); + text_info->stream = svn_stream_from_aprfile2(target->file, + FALSE, result_pool); /* Also check the file for local mods and the Xbit. */ SVN_ERR(svn_wc_text_modified_p2(&target->local_mods, wc_ctx, @@ -475,16 +490,16 @@ init_patch_target(patch_target_t **patch_target, /* Expand keywords in the patched file. * Repair newlines if svn:eol-style dictates a particular style. */ - repair_eol = (target->eol_style == svn_subst_eol_style_fixed || - target->eol_style == svn_subst_eol_style_native); - target->patched = svn_subst_stream_translated( - patched_raw, target->eol_str, repair_eol, - target->keywords, TRUE, result_pool); + repair_eol = (text_info->eol_style == svn_subst_eol_style_fixed + || text_info->eol_style == svn_subst_eol_style_native); + text_info->patched = svn_subst_stream_translated( + patched_raw, text_info->eol_str, repair_eol, + text_info->keywords, TRUE, result_pool); /* We'll also need a stream to write rejected hunks to. * We don't expand keywords, nor normalise line-endings, * in reject files. */ - SVN_ERR(svn_stream_open_unique(&target->reject, + SVN_ERR(svn_stream_open_unique(&text_info->reject, &target->reject_path, NULL, remove_tempfiles ? svn_io_file_del_on_pool_cleanup : @@ -498,7 +513,7 @@ init_patch_target(patch_target_t **patch_target, target->canon_path_from_patchfile, APR_EOL_STR); len = strlen(diff_header); - SVN_ERR(svn_stream_write(target->reject, diff_header, &len)); + SVN_ERR(svn_stream_write(text_info->reject, diff_header, &len)); } *patch_target = target; @@ -510,7 +525,7 @@ init_patch_target(patch_target_t **patch_target, * Do temporary allocations in SCRATCH_POOL. */ static svn_error_t * -read_line(patch_target_t *target, +read_line(text_info_t *text_info, const char **line, apr_pool_t *scratch_pool, apr_pool_t *result_pool) @@ -518,33 +533,33 @@ static svn_error_t * svn_stringbuf_t *line_raw; const char *eol_str; - if (target->eof) + if (text_info->eof) { *line = ""; return SVN_NO_ERROR; } - SVN_ERR_ASSERT(target->current_line <= target->lines->nelts + 1); - if (target->current_line == target->lines->nelts + 1) + SVN_ERR_ASSERT(text_info->current_line <= text_info->lines->nelts + 1); + if (text_info->current_line == text_info->lines->nelts + 1) { svn_stream_mark_t *mark; - SVN_ERR(svn_stream_mark(target->stream, &mark, target->pool)); - APR_ARRAY_PUSH(target->lines, svn_stream_mark_t *) = mark; + SVN_ERR(svn_stream_mark(text_info->stream, &mark, text_info->pool)); + APR_ARRAY_PUSH(text_info->lines, svn_stream_mark_t *) = mark; } - SVN_ERR(svn_stream_readline_detect_eol(target->stream, &line_raw, - &eol_str, &target->eof, + SVN_ERR(svn_stream_readline_detect_eol(text_info->stream, &line_raw, + &eol_str, &text_info->eof, scratch_pool)); - if (target->eol_style == svn_subst_eol_style_none) - target->eol_str = eol_str; + if (text_info->eol_style == svn_subst_eol_style_none) + text_info->eol_str = eol_str; /* Contract keywords. */ SVN_ERR(svn_subst_translate_cstring2(line_raw->data, line, NULL, FALSE, - target->keywords, FALSE, + text_info->keywords, FALSE, result_pool)); - if (! target->eof) - target->current_line++; + if (! text_info->eof) + text_info->current_line++; return SVN_NO_ERROR; } @@ -554,7 +569,7 @@ static svn_error_t * * Do temporary allocations in SCRATCH_POOL. */ static svn_error_t * -seek_to_line(patch_target_t *target, svn_linenum_t line, +seek_to_line(text_info_t *text_info, svn_linenum_t line, apr_pool_t *scratch_pool) { svn_linenum_t saved_line; @@ -562,36 +577,36 @@ static svn_error_t * SVN_ERR_ASSERT(line > 0); - if (line == target->current_line) + if (line == text_info->current_line) return SVN_NO_ERROR; - saved_line = target->current_line; - saved_eof = target->eof; + saved_line = text_info->current_line; + saved_eof = text_info->eof; - if (line <= target->lines->nelts) + if (line <= text_info->lines->nelts) { svn_stream_mark_t *mark; - mark = APR_ARRAY_IDX(target->lines, line - 1, svn_stream_mark_t *); - SVN_ERR(svn_stream_seek(target->stream, mark)); - target->current_line = line; + mark = APR_ARRAY_IDX(text_info->lines, line - 1, svn_stream_mark_t *); + SVN_ERR(svn_stream_seek(text_info->stream, mark)); + text_info->current_line = line; } else { const char *dummy; apr_pool_t *iterpool = svn_pool_create(scratch_pool); - while (! target->eof && target->current_line < line) + while (! text_info->eof && text_info->current_line < line) { svn_pool_clear(iterpool); - SVN_ERR(read_line(target, &dummy, iterpool, iterpool)); + SVN_ERR(read_line(text_info, &dummy, iterpool, iterpool)); } svn_pool_destroy(iterpool); } /* After seeking backwards from EOF position clear EOF indicator. */ - if (saved_eof && saved_line > target->current_line) - target->eof = FALSE; + if (saved_eof && saved_line > text_info->current_line) + text_info->eof = FALSE; return SVN_NO_ERROR; } @@ -605,7 +620,7 @@ static svn_error_t * * rather than the original hunk text. * Do temporary allocations in POOL. */ static svn_error_t * -match_hunk(svn_boolean_t *matched, patch_target_t *target, +match_hunk(svn_boolean_t *matched, text_info_t *text_info, const svn_hunk_t *hunk, int fuzz, svn_boolean_t ignore_whitespace, svn_boolean_t match_modified, apr_pool_t *pool) @@ -623,10 +638,10 @@ static svn_error_t * *matched = FALSE; - if (target->eof) + if (text_info->eof) return SVN_NO_ERROR; - saved_line = target->current_line; + saved_line = text_info->current_line; lines_read = 0; lines_matched = FALSE; original_length = svn_diff_hunk_get_original_length(hunk); @@ -656,10 +671,10 @@ static svn_error_t * SVN_ERR(svn_subst_translate_cstring2(hunk_line->data, &hunk_line_translated, NULL, FALSE, - target->keywords, FALSE, + text_info->keywords, FALSE, iterpool)); lines_read++; - SVN_ERR(read_line(target, &target_line, iterpool, iterpool)); + SVN_ERR(read_line(text_info, &target_line, iterpool, iterpool)); if (! hunk_eof) { if (lines_read <= fuzz && leading_context > fuzz) @@ -686,11 +701,11 @@ static svn_error_t * } } } - while (lines_matched && ! (hunk_eof || target->eof)); + while (lines_matched && ! (hunk_eof || text_info->eof)); if (hunk_eof) *matched = lines_matched; - else if (target->eof) + else if (text_info->eof) { /* If the target has no newline at end-of-file, we get an EOF * indication for the target earlier than we do get it for the hunk. */ @@ -707,7 +722,7 @@ static svn_error_t * else *matched = FALSE; } - SVN_ERR(seek_to_line(target, saved_line, iterpool)); + SVN_ERR(seek_to_line(text_info, saved_line, iterpool)); svn_pool_destroy(iterpool); @@ -729,7 +744,7 @@ static svn_error_t * * Call cancel CANCEL_FUNC with baton CANCEL_BATON to trigger cancellation. * Do all allocations in POOL. */ static svn_error_t * -scan_for_match(svn_linenum_t *matched_line, patch_target_t *target, +scan_for_match(svn_linenum_t *matched_line, text_info_t *text_info, const svn_hunk_t *hunk, svn_boolean_t match_first, svn_linenum_t upper_line, int fuzz, svn_boolean_t ignore_whitespace, @@ -741,8 +756,8 @@ static svn_error_t * *matched_line = 0; iterpool = svn_pool_create(pool); - while ((target->current_line < upper_line || upper_line == 0) && - ! target->eof) + while ((text_info->current_line < upper_line || upper_line == 0) && + ! text_info->eof) { svn_boolean_t matched; int i; @@ -752,19 +767,19 @@ static svn_error_t * if (cancel_func) SVN_ERR((cancel_func)(cancel_baton)); - SVN_ERR(match_hunk(&matched, target, hunk, fuzz, ignore_whitespace, + SVN_ERR(match_hunk(&matched, text_info, hunk, fuzz, ignore_whitespace, match_modified, iterpool)); if (matched) { svn_boolean_t taken = FALSE; /* Don't allow hunks to match at overlapping locations. */ - for (i = 0; i < target->hunks->nelts; i++) + for (i = 0; i < text_info->hunks->nelts; i++) { const hunk_info_t *hi; svn_linenum_t length; - hi = APR_ARRAY_IDX(target->hunks, i, const hunk_info_t *); + hi = APR_ARRAY_IDX(text_info->hunks, i, const hunk_info_t *); if (match_modified) length = svn_diff_hunk_get_modified_length(hi->hunk); @@ -772,22 +787,23 @@ static svn_error_t * length = svn_diff_hunk_get_original_length(hi->hunk); taken = (! hi->rejected && - target->current_line >= hi->matched_line && - target->current_line < (hi->matched_line + length)); + text_info->current_line >= hi->matched_line && + text_info->current_line < (hi->matched_line + length)); if (taken) break; } if (! taken) { - *matched_line = target->current_line; + *matched_line = text_info->current_line; if (match_first) break; } } - if (! target->eof) - SVN_ERR(seek_to_line(target, target->current_line + 1, iterpool)); + if (! text_info->eof) + SVN_ERR(seek_to_line(text_info, text_info->current_line + 1, + iterpool)); } svn_pool_destroy(iterpool); @@ -834,11 +850,13 @@ match_existing_file(svn_boolean_t *match, iterpool, iterpool)); /* Contract keywords. */ SVN_ERR(svn_subst_translate_cstring2(line->data, &line_translated, - NULL, FALSE, target->keywords, + NULL, FALSE, + target->text_info->keywords, FALSE, iterpool)); SVN_ERR(svn_subst_translate_cstring2(hunk_line->data, &hunk_line_translated, - NULL, FALSE, target->keywords, + NULL, FALSE, + target->text_info->keywords, FALSE, iterpool)); lines_matched = ! strcmp(line_translated, hunk_line_translated); if (eof != hunk_eof) @@ -868,6 +886,7 @@ match_existing_file(svn_boolean_t *match, * Do temporary allocations in POOL. */ static svn_error_t * get_hunk_info(hunk_info_t **hi, patch_target_t *target, + text_info_t *text_info, const svn_hunk_t *hunk, int fuzz, svn_boolean_t ignore_whitespace, svn_cancel_func_t cancel_func, void *cancel_baton, @@ -911,7 +930,7 @@ get_hunk_info(hunk_info_t **hi, patch_target_t *ta } else if (original_start > 0 && target->kind_on_disk == svn_node_file) { - svn_linenum_t saved_line = target->current_line; + svn_linenum_t saved_line = text_info->current_line; svn_linenum_t modified_start; /* Check if the hunk is already applied. @@ -928,8 +947,9 @@ get_hunk_info(hunk_info_t **hi, patch_target_t *ta } else { - SVN_ERR(seek_to_line(target, modified_start, scratch_pool)); - SVN_ERR(scan_for_match(&matched_line, target, hunk, TRUE, + SVN_ERR(seek_to_line(text_info, modified_start, scratch_pool)); + SVN_ERR(scan_for_match(&matched_line, text_info, + hunk, TRUE, modified_start + 1, fuzz, ignore_whitespace, TRUE, cancel_func, cancel_baton, @@ -944,14 +964,14 @@ get_hunk_info(hunk_info_t **hi, patch_target_t *ta { /* Scan for a match at the line where the hunk thinks it * should be going. */ - SVN_ERR(seek_to_line(target, original_start, scratch_pool)); - if (target->current_line != original_start) + SVN_ERR(seek_to_line(text_info, original_start, scratch_pool)); + if (text_info->current_line != original_start) { /* Seek failed. */ matched_line = 0; } else - SVN_ERR(scan_for_match(&matched_line, target, hunk, TRUE, + SVN_ERR(scan_for_match(&matched_line, text_info, hunk, TRUE, original_start + 1, fuzz, ignore_whitespace, FALSE, cancel_func, cancel_baton, @@ -960,11 +980,11 @@ get_hunk_info(hunk_info_t **hi, patch_target_t *ta if (matched_line != original_start) { /* Scan the whole file again from the start. */ - SVN_ERR(seek_to_line(target, 1, scratch_pool)); + SVN_ERR(seek_to_line(text_info, 1, scratch_pool)); /* Scan forward towards the hunk's line and look for a line * where the hunk matches. */ - SVN_ERR(scan_for_match(&matched_line, target, hunk, FALSE, + SVN_ERR(scan_for_match(&matched_line, text_info, hunk, FALSE, original_start, fuzz, ignore_whitespace, FALSE, cancel_func, cancel_baton, @@ -976,15 +996,15 @@ get_hunk_info(hunk_info_t **hi, patch_target_t *ta { /* Scan forward towards the end of the file and look * for a line where the hunk matches. */ - SVN_ERR(scan_for_match(&matched_line, target, hunk, TRUE, 0, - fuzz, ignore_whitespace, FALSE, - cancel_func, cancel_baton, + SVN_ERR(scan_for_match(&matched_line, text_info, hunk, + TRUE, 0, fuzz, ignore_whitespace, + FALSE, cancel_func, cancel_baton, scratch_pool)); } } } - SVN_ERR(seek_to_line(target, saved_line, scratch_pool)); + SVN_ERR(seek_to_line(text_info, saved_line, scratch_pool)); } else { @@ -1026,23 +1046,24 @@ try_stream_write(svn_stream_t *stream, const char * If LINE is zero, copy lines until end-of-file has been reached. * Do all allocations in POOL. */ static svn_error_t * -copy_lines_to_target(patch_target_t *target, svn_linenum_t line, - apr_pool_t *pool) +copy_lines_to_target(text_info_t *text_info, svn_linenum_t line, + const char *patched_path, apr_pool_t *pool) { apr_pool_t *iterpool; iterpool = svn_pool_create(pool); - while ((target->current_line < line || line == 0) && ! target->eof) + while ((text_info->current_line < line || line == 0) && ! text_info->eof) { const char *target_line; svn_pool_clear(iterpool); - SVN_ERR(read_line(target, &target_line, iterpool, iterpool)); - if (! target->eof) - target_line = apr_pstrcat(iterpool, target_line, target->eol_str, NULL); + SVN_ERR(read_line(text_info, &target_line, iterpool, iterpool)); + if (! text_info->eof) + target_line = apr_pstrcat(iterpool, target_line, text_info->eol_str, + NULL); - SVN_ERR(try_stream_write(target->patched, target->patched_path, + SVN_ERR(try_stream_write(text_info->patched, patched_path, target_line, strlen(target_line), iterpool)); } svn_pool_destroy(iterpool); @@ -1054,7 +1075,8 @@ static svn_error_t * * reject stream of TARGET, and mark TARGET as having had rejects. * Do temporary allocations in POOL. */ static svn_error_t * -reject_hunk(patch_target_t *target, hunk_info_t *hi, apr_pool_t *pool) +reject_hunk(patch_target_t *target, text_info_t *text_info, + hunk_info_t *hi, apr_pool_t *pool) { const char *hunk_header; apr_size_t len; @@ -1068,7 +1090,7 @@ static svn_error_t * svn_diff_hunk_get_modified_length(hi->hunk), APR_EOL_STR); len = strlen(hunk_header); - SVN_ERR(svn_stream_write(target->reject, hunk_header, &len)); + SVN_ERR(svn_stream_write(text_info->reject, hunk_header, &len)); iterpool = svn_pool_create(pool); do @@ -1083,11 +1105,11 @@ static svn_error_t * if (! eof) { if (hunk_line->len >= 1) - SVN_ERR(try_stream_write(target->reject, target->reject_path, + SVN_ERR(try_stream_write(text_info->reject, target->reject_path, hunk_line->data, hunk_line->len, iterpool)); if (eol_str) - SVN_ERR(try_stream_write(target->reject, target->reject_path, + SVN_ERR(try_stream_write(text_info->reject, target->reject_path, eol_str, strlen(eol_str), iterpool)); } } @@ -1102,7 +1124,8 @@ static svn_error_t * /* Write the modified text of hunk described by HI to the patched * stream of TARGET. Do temporary allocations in POOL. */ static svn_error_t * -apply_hunk(patch_target_t *target, hunk_info_t *hi, apr_pool_t *pool) +apply_hunk(patch_target_t *target, text_info_t *text_info, + hunk_info_t *hi, apr_pool_t *pool) { svn_linenum_t lines_read; svn_boolean_t eof; @@ -1116,19 +1139,19 @@ static svn_error_t * * Also copy leading lines of context which matched with fuzz. * The target has changed on the fuzzy-matched lines, * so we should retain the target's version of those lines. */ - SVN_ERR(copy_lines_to_target(target, hi->matched_line + hi->fuzz, - pool)); + SVN_ERR(copy_lines_to_target(text_info, hi->matched_line + hi->fuzz, + target->patched_path, pool)); /* Skip the target's version of the hunk. * Don't skip trailing lines which matched with fuzz. */ - line = target->current_line + + line = text_info->current_line + svn_diff_hunk_get_original_length(hi->hunk) - (2 * hi->fuzz); - SVN_ERR(seek_to_line(target, line, pool)); - if (target->current_line != line && ! target->eof) + SVN_ERR(seek_to_line(text_info, line, pool)); + if (text_info->current_line != line && ! text_info->eof) { /* Seek failed, reject this hunk. */ hi->rejected = TRUE; - SVN_ERR(reject_hunk(target, hi, pool)); + SVN_ERR(reject_hunk(target, text_info, hi, pool)); return SVN_NO_ERROR; } } @@ -1153,17 +1176,17 @@ static svn_error_t * lines_read <= svn_diff_hunk_get_modified_length(hi->hunk) - hi->fuzz) { if (hunk_line->len >= 1) - SVN_ERR(try_stream_write(target->patched, target->patched_path, + SVN_ERR(try_stream_write(text_info->patched, target->patched_path, hunk_line->data, hunk_line->len, iterpool)); if (eol_str) { /* Use the EOL as it was read from the patch file, * unless the target's EOL style is set by svn:eol-style */ - if (target->eol_style != svn_subst_eol_style_none) - eol_str = target->eol_str; + if (text_info->eol_style != svn_subst_eol_style_none) + eol_str = text_info->eol_str; - SVN_ERR(try_stream_write(target->patched, target->patched_path, + SVN_ERR(try_stream_write(text_info->patched, target->patched_path, eol_str, strlen(eol_str), iterpool)); } } @@ -1229,13 +1252,13 @@ send_patch_notification(const patch_target_t *targ apr_pool_t *iterpool; iterpool = svn_pool_create(pool); - for (i = 0; i < target->hunks->nelts; i++) + for (i = 0; i < target->text_info->hunks->nelts; i++) { hunk_info_t *hi; svn_pool_clear(iterpool); - hi = APR_ARRAY_IDX(target->hunks, i, hunk_info_t *); + hi = APR_ARRAY_IDX(target->text_info->hunks, i, hunk_info_t *); if (hi->already_applied) action = svn_wc_notify_patch_hunk_already_applied; @@ -1335,7 +1358,7 @@ apply_one_patch(patch_target_t **patch_target, svn * If no match is found initially, try with fuzz. */ do { - SVN_ERR(get_hunk_info(&hi, target, hunk, fuzz, + SVN_ERR(get_hunk_info(&hi, target, target->text_info, hunk, fuzz, ignore_whitespace, cancel_func, cancel_baton, result_pool, iterpool)); @@ -1343,31 +1366,32 @@ apply_one_patch(patch_target_t **patch_target, svn } while (hi->rejected && fuzz <= MAX_FUZZ && ! hi->already_applied); - APR_ARRAY_PUSH(target->hunks, hunk_info_t *) = hi; + APR_ARRAY_PUSH(target->text_info->hunks, hunk_info_t *) = hi; } /* Apply or reject hunks. */ - for (i = 0; i < target->hunks->nelts; i++) + for (i = 0; i < target->text_info->hunks->nelts; i++) { hunk_info_t *hi; svn_pool_clear(iterpool); - hi = APR_ARRAY_IDX(target->hunks, i, hunk_info_t *); + hi = APR_ARRAY_IDX(target->text_info->hunks, i, hunk_info_t *); if (hi->already_applied) continue; else if (hi->rejected) - SVN_ERR(reject_hunk(target, hi, iterpool)); + SVN_ERR(reject_hunk(target, target->text_info, hi, iterpool)); else - SVN_ERR(apply_hunk(target, hi, iterpool)); + SVN_ERR(apply_hunk(target, target->text_info, hi, iterpool)); } svn_pool_destroy(iterpool); if (target->kind_on_disk == svn_node_file) { /* Copy any remaining lines to target. */ - SVN_ERR(copy_lines_to_target(target, 0, scratch_pool)); - if (! target->eof) + SVN_ERR(copy_lines_to_target(target->text_info, 0, + target->patched_path, scratch_pool)); + if (! target->text_info->eof) { /* We could not copy the entire target file to the temporary file, * and would truncate the target if we copied the temporary file @@ -1379,9 +1403,9 @@ apply_one_patch(patch_target_t **patch_target, svn /* Close the streams of the target so that their content is flushed * to disk. This will also close underlying streams and files. */ if (target->kind_on_disk == svn_node_file) - SVN_ERR(svn_stream_close(target->stream)); - SVN_ERR(svn_stream_close(target->patched)); - SVN_ERR(svn_stream_close(target->reject)); + SVN_ERR(svn_stream_close(target->text_info->stream)); + SVN_ERR(svn_stream_close(target->text_info->patched)); + SVN_ERR(svn_stream_close(target->text_info->reject)); if (! target->skipped) {