Author: stsp Date: Mon Nov 28 19:06:34 2011 New Revision: 1207512 URL: http://svn.apache.org/viewvc?rev=1207512&view=rev Log: On the 1.7.x-svn-patch-eol-fixes branch, merge the following from trunk:
r1150344: Merged to avoid conflicts in diff parsing test. r1158923: Adds a cmdline regression test for issue #3991. r1158929: Adds a new C diff parsing regression test for issue #3991. r1166267: Merged to prevent conflicts in diff_tests.py. r1206576: Tweak 'svn diff' output for prop values not terminated with EOL. r1206718: Fix issue #3814. r1206719: Follow-up fix for JavaHL tests. r1206724: Fix issue #3991. r1206741: Fixes the #3991 C diff parsing test to make it PASS. r1206748: Remove an obsolete comment. Modified: subversion/branches/1.7.x-svn-patch-eol-fixes/ (props changed) subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/libsvn_client/diff.c subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/libsvn_client/patch.c subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/libsvn_diff/parse-diff.c subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/svnlook/main.c subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/depth_tests.py subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/diff_tests.py subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/patch_tests.py subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/special_tests.py subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/libsvn_diff/parse-diff-test.c Propchange: subversion/branches/1.7.x-svn-patch-eol-fixes/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Mon Nov 28 19:06:34 2011 @@ -69,4 +69,4 @@ /subversion/branches/tree-conflicts:868291-873154 /subversion/branches/tree-conflicts-notify:873926-874008 /subversion/branches/uris-as-urls:1060426-1064427 -/subversion/trunk:1146013,1146121,1146219,1146222,1146274,1146492,1146555,1146606,1146620,1146684,1146781,1146832,1146834,1146870,1146899,1146904,1147293,1147299,1147309,1147882,1148071,1148083,1148094,1148131,1148374,1148424,1148566,1148588,1148652,1148662,1148699,1148853,1148877,1148882,1148936,1149103,1149105,1149135,1149141,1149160,1149228,1149240,1149343,1149371-1149372,1149377,1149398,1149401,1149539,1149572,1149627,1149675,1149701,1149713,1150242,1150254,1150260-1150261,1150266,1150302,1150327,1150368,1150372,1150441,1150506,1150812,1150853,1151036,1151177,1151610,1151854,1151906,1151911,1152129,1152140,1152189-1152190,1152267,1152282,1152286,1152726,1152809,1153138,1153141,1153416,1153540,1153566,1153799,1153807,1153968,1154009,1154023,1154115,1154119,1154121,1154144,1154155,1154159,1154165,1154215,1154225,1154273,1154278,1154379,1154382,1154461,1154717-1154718,1154733,1154908,1154982,1155015,1155044,1155124,1155131,1155160,1155313,1155334,1155391,1155404,1156085,115 6098,1156216,1156218,1156312,1156527,1156717,1156721,1156750,1156827,1156838,1157416,1158187,1158193-1158194,1158196,1158201,1158207,1158209-1158210,1158217,1158285,1158288,1158303,1158309,1158407,1158419,1158421,1158436,1158455,1158616-1158617,1158634,1158854,1158875,1158886,1158893,1158896,1158919,1158924,1158963,1159093,1159098,1159101,1159132,1159136,1159148,1159230,1159275,1159400,1159686,1159760,1159772,1160605,1160671,1160682,1160704-1160705,1160756,1161063,1161080,1161185,1161210,1161683,1161721,1162024,1162033,1162201,1162516,1162880,1162974,1162995,1163243,1163383,1163557,1163792,1163953,1164027,1164386,1164426,1164517,1164535,1164554,1164580,1164614,1164645,1164760,1164765,1166500,1166555,1166678,1167062,1167173,1167209,1167269,1167503,1167659,1167681,1169524,1169531,1169650,1171708,1173111,1173425,1173639,1174051,1174060,1174652,1174761,1174797-1174798,1174806,1175888,1176915,1176949,1177001,1177492,1177732,1178280,1178282,1178942,1179680,1179767,1180154,1181090, 1181110,1181155,1181215,1181609,1181666,1182115,1182527,1182771,1182904,1182909,1183054,1183263,1183347,1185222,1185242,1185280,1185282,1185730,1185738,1185746,1185763,1185768,1185886,1185911,1185918,1186059,1186092,1186101,1186107,1186109,1186121,1186231,1186240,1186422,1186434,1186732,1186755,1186784,1186815,1186928,1186944,1186981,1186983,1187311,1187676,1187695,1188609,1188774,1189190,1189261,1189395,1189580,1189665,1197135,1197998,1199876,1199950,1200837,1201002,1201824,1202135,1202187,1202630,1202807,1203546,1203651,1203653,1204167,1204478,1204610,1204673,1205193,1205726,1206523,1206533 +/subversion/trunk:1146013,1146121,1146219,1146222,1146274,1146492,1146555,1146606,1146620,1146684,1146781,1146832,1146834,1146870,1146899,1146904,1147293,1147299,1147309,1147882,1148071,1148083,1148094,1148131,1148374,1148424,1148566,1148588,1148652,1148662,1148699,1148853,1148877,1148882,1148936,1149103,1149105,1149135,1149141,1149160,1149228,1149240,1149343,1149371-1149372,1149377,1149398,1149401,1149539,1149572,1149627,1149675,1149701,1149713,1150242,1150254,1150260-1150261,1150266,1150302,1150327,1150344,1150368,1150372,1150441,1150506,1150812,1150853,1151036,1151177,1151610,1151854,1151906,1151911,1152129,1152140,1152189-1152190,1152267,1152282,1152286,1152726,1152809,1153138,1153141,1153416,1153540,1153566,1153799,1153807,1153968,1154009,1154023,1154115,1154119,1154121,1154144,1154155,1154159,1154165,1154215,1154225,1154273,1154278,1154379,1154382,1154461,1154717-1154718,1154733,1154908,1154982,1155015,1155044,1155124,1155131,1155160,1155313,1155334,1155391,1155404,115 6085,1156098,1156216,1156218,1156312,1156527,1156717,1156721,1156750,1156827,1156838,1157416,1158187,1158193-1158194,1158196,1158201,1158207,1158209-1158210,1158217,1158285,1158288,1158303,1158309,1158407,1158419,1158421,1158436,1158455,1158616-1158617,1158634,1158854,1158875,1158886,1158893,1158896,1158919,1158923-1158924,1158929,1158963,1159093,1159098,1159101,1159132,1159136,1159148,1159230,1159275,1159400,1159686,1159760,1159772,1160605,1160671,1160682,1160704-1160705,1160756,1161063,1161080,1161185,1161210,1161683,1161721,1162024,1162033,1162201,1162516,1162880,1162974,1162995,1163243,1163383,1163557,1163792,1163953,1164027,1164386,1164426,1164517,1164535,1164554,1164580,1164614,1164645,1164760,1164765,1166267,1166500,1166555,1166678,1167062,1167173,1167209,1167269,1167503,1167659,1167681,1169524,1169531,1169650,1171708,1173111,1173425,1173639,1174051,1174060,1174652,1174761,1174797-1174798,1174806,1175888,1176915,1176949,1177001,1177492,1177732,1178280,1178282,1178942, 1179680,1179767,1180154,1181090,1181110,1181155,1181215,1181609,1181666,1182115,1182527,1182771,1182904,1182909,1183054,1183263,1183347,1185222,1185242,1185280,1185282,1185730,1185738,1185746,1185763,1185768,1185886,1185911,1185918,1186059,1186092,1186101,1186107,1186109,1186121,1186231,1186240,1186422,1186434,1186732,1186755,1186784,1186815,1186928,1186944,1186981,1186983,1187311,1187676,1187695,1188609,1188774,1189190,1189261,1189395,1189580,1189665,1197135,1197998,1199876,1199950,1200837,1201002,1201824,1202135,1202187,1202630,1202807,1203546,1203651,1203653,1204167,1204478,1204610,1204673,1205193,1205726,1206523,1206533,1206576,1206718-1206719,1206724,1206741,1206748 Modified: subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java?rev=1207512&r1=1207511&r2=1207512&view=diff ============================================================================== --- subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java (original) +++ subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java Mon Nov 28 19:06:34 2011 @@ -2736,7 +2736,7 @@ public class BasicTests extends SVNTests "## -0,0 +1 ##" + NL + "+Test property value." + NL; - setprop(aPath, "testprop", "Test property value."); + setprop(aPath, "testprop", "Test property value." + NL); client.diff(aPath, Revision.BASE, aPath, Revision.WORKING, wcPath, diffOutput.getPath(), Depth.infinity, null, true, true, false, false); @@ -2754,7 +2754,7 @@ public class BasicTests extends SVNTests "## -0,0 +1 ##" + NL + "+Test property value." + NL; - setprop(aPath, "testprop", "Test property value."); + setprop(aPath, "testprop", "Test property value." + NL); client.diff(aPath, Revision.BASE, aPath, Revision.WORKING, aPath, diffOutput.getPath(), Depth.infinity, null, true, true, false, false); Modified: subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java?rev=1207512&r1=1207511&r2=1207512&view=diff ============================================================================== --- subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java (original) +++ subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/bindings/javahl/tests/org/tigris/subversion/javahl/BasicTests.java Mon Nov 28 19:06:34 2011 @@ -2674,7 +2674,8 @@ public class BasicTests extends SVNTests "## -0,0 +1 ##" + NL + "+Test property value." + NL; - client.propertySet(aPath, "testprop", "Test property value.", false); + client.propertySet(aPath, "testprop", "Test property value." + NL, + false); client.diff(aPath, Revision.BASE, aPath, Revision.WORKING, wcPath, diffOutput.getPath(), Depth.infinity, null, true, true, false); @@ -2692,7 +2693,8 @@ public class BasicTests extends SVNTests "## -0,0 +1 ##" + NL + "+Test property value." + NL; - client.propertySet(aPath, "testprop", "Test property value.", false); + client.propertySet(aPath, "testprop", "Test property value." + NL, + false); client.diff(aPath, Revision.BASE, aPath, Revision.WORKING, aPath, diffOutput.getPath(), Depth.infinity, null, true, true, false); Modified: subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/libsvn_client/diff.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/libsvn_client/diff.c?rev=1207512&r1=1207511&r2=1207512&view=diff ============================================================================== --- subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/libsvn_client/diff.c (original) +++ subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/libsvn_client/diff.c Mon Nov 28 19:06:34 2011 @@ -166,18 +166,25 @@ display_mergeinfo_diff(const char *old_m If TOKEN is empty, or is already terminated by an EOL marker, return TOKEN unmodified. Else, return a new string consisting of the concatenation of TOKEN and the system's default EOL marker. - The new string is allocated from POOL. */ + The new string is allocated from POOL. + If HAD_EOL is not NULL, indicate in *HAD_EOL if the token had a EOL. */ static const svn_string_t * -maybe_append_eol(const svn_string_t *token, apr_pool_t *pool) +maybe_append_eol(const svn_string_t *token, svn_boolean_t *had_eol, + apr_pool_t *pool) { const char *curp; + if (had_eol) + *had_eol = FALSE; + if (token->len == 0) return token; curp = token->data + token->len - 1; if (*curp == '\r') { + if (had_eol) + *had_eol = TRUE; return token; } else if (*curp != '\n') @@ -186,6 +193,8 @@ maybe_append_eol(const svn_string_t *tok } else { + if (had_eol) + *had_eol = TRUE; return token; } } @@ -683,17 +692,18 @@ display_prop_diffs(const apr_array_heade const svn_string_t *tmp; const svn_string_t *orig; const svn_string_t *val; + svn_boolean_t val_has_eol; /* The last character in a property is often not a newline. - Since the diff is not useful anyway for patching properties an - eol character is appended when needed to remove those pescious - ' \ No newline at end of file' lines. */ + An eol character is appended to prevent the diff API to add a + ' \ No newline at end of file' line. We add + ' \ No newline at end of property' manually if needed. */ tmp = original_value ? original_value : svn_string_create("", pool); - orig = maybe_append_eol(tmp, pool); + orig = maybe_append_eol(tmp, NULL, pool); tmp = propchange->value ? propchange->value : svn_string_create("", pool); - val = maybe_append_eol(tmp, pool); + val = maybe_append_eol(tmp, &val_has_eol, pool); SVN_ERR(svn_diff_mem_string_diff(&diff, orig, val, &options, pool)); @@ -709,7 +719,12 @@ display_prop_diffs(const apr_array_heade svn_dirent_local_style(path, pool), encoding, orig, val, pool)); SVN_ERR(svn_stream_close(os)); - + if (!val_has_eol) + { + const char *s = "\\ No newline at end of property" APR_EOL_STR; + apr_size_t len = strlen(s); + SVN_ERR(svn_stream_write(os, s, &len)); + } } } Modified: subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/libsvn_client/patch.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/libsvn_client/patch.c?rev=1207512&r1=1207511&r2=1207512&view=diff ============================================================================== --- subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/libsvn_client/patch.c (original) +++ subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/libsvn_client/patch.c Mon Nov 28 19:06:34 2011 @@ -1677,7 +1677,7 @@ apply_hunk(patch_target_t *target, targe &eol_str, &eof, iterpool, iterpool)); lines_read++; - if (! eof && lines_read > hi->fuzz && + if (lines_read > hi->fuzz && lines_read <= svn_diff_hunk_get_modified_length(hi->hunk) - hi->fuzz) { apr_size_t len; Modified: subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/libsvn_diff/parse-diff.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/libsvn_diff/parse-diff.c?rev=1207512&r1=1207511&r2=1207512&view=diff ============================================================================== --- subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/libsvn_diff/parse-diff.c (original) +++ subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/libsvn_diff/parse-diff.c Mon Nov 28 19:06:34 2011 @@ -631,17 +631,45 @@ parse_next_hunk(svn_diff_hunk_t **hunk, SVN_ERR(readline(apr_file, &line, NULL, &eof, APR_SIZE_MAX, iterpool, iterpool)); - if (! eof) - { - /* Update line offset for next iteration. */ - pos = 0; - SVN_ERR(svn_io_file_seek(apr_file, APR_CUR, &pos, iterpool)); - } + /* Update line offset for next iteration. */ + pos = 0; + SVN_ERR(svn_io_file_seek(apr_file, APR_CUR, &pos, iterpool)); /* Lines starting with a backslash are comments, such as * "\ No newline at end of file". */ if (line->data[0] == '\\') - continue; + { + if (in_hunk && + ((!is_property && + strcmp(line->data, "\\ No newline at end of file") == 0) || + (is_property && + strcmp(line->data, "\\ No newline at end of property") == 0))) + { + char eolbuf[2]; + apr_size_t len; + apr_off_t off; + + /* Comment terminates the hunk text and says the hunk text + * has no trailing EOL. Snip off trailing EOL which is part + * of the patch file but not part of the hunk text. */ + off = last_line - 2; + SVN_ERR(svn_io_file_seek(apr_file, APR_SET, &off, iterpool)); + len = sizeof(eolbuf); + SVN_ERR(svn_io_file_read_full2(apr_file, eolbuf, len, &len, + &eof, iterpool)); + if (eolbuf[0] == '\r' && eolbuf[1] == '\n') + end = last_line - 2; + else if (eolbuf[1] == '\n') + end = last_line - 1; + else if (eolbuf[1] == '\r') + end = last_line - 1; + else + end = last_line; + break; + } + + continue; + } if (in_hunk) { @@ -701,9 +729,17 @@ parse_next_hunk(svn_diff_hunk_t **hunk, } else { - /* The start of the current line marks the first byte - * after the hunk text. */ - end = last_line; + if (eof) + { + /* The hunk ends at EOF. */ + end = pos; + } + else + { + /* The start of the current line marks the first byte + * after the hunk text. */ + end = last_line; + } break; /* Hunk was empty or has been read. */ } Modified: subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/svnlook/main.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/svnlook/main.c?rev=1207512&r1=1207511&r2=1207512&view=diff ============================================================================== --- subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/svnlook/main.c (original) +++ subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/svnlook/main.c Mon Nov 28 19:06:34 2011 @@ -784,18 +784,25 @@ generate_label(const char **label, If TOKEN is empty, or is already terminated by an EOL marker, return TOKEN unmodified. Else, return a new string consisting of the concatenation of TOKEN and the system's default EOL marker. - The new string is allocated from POOL. */ + The new string is allocated from POOL. + If HAD_EOL is not NULL, indicate in *HAD_EOL if the token had a EOL. */ static const svn_string_t * -maybe_append_eol(const svn_string_t *token, apr_pool_t *pool) +maybe_append_eol(const svn_string_t *token, svn_boolean_t *had_eol, + apr_pool_t *pool) { const char *curp; + if (had_eol) + *had_eol = FALSE; + if (token->len == 0) return token; curp = token->data + token->len - 1; if (*curp == '\r') { + if (had_eol) + *had_eol = TRUE; return token; } else if (*curp != '\n') @@ -804,6 +811,8 @@ maybe_append_eol(const svn_string_t *tok } else { + if (had_eol) + *had_eol = TRUE; return token; } } @@ -860,19 +869,20 @@ display_prop_diffs(const apr_array_heade const svn_string_t *tmp; const svn_string_t *orig; const svn_string_t *val; + svn_boolean_t val_has_eol; SVN_ERR(svn_stream_for_stdout(&out, pool)); /* The last character in a property is often not a newline. - Since the diff is not useful anyway for patching properties an - eol character is appended when needed to remove those pescious - ' \ No newline at end of file' lines. */ + An eol character is appended to prevent the diff API to add a + ' \ No newline at end of file' line. We add + ' \ No newline at end of property' manually if needed. */ tmp = orig_value ? orig_value : svn_string_create("", pool); - orig = maybe_append_eol(tmp, pool); + orig = maybe_append_eol(tmp, NULL, pool); tmp = pc->value ? pc->value : svn_string_create("", pool); - val = maybe_append_eol(tmp, pool); + val = maybe_append_eol(tmp, &val_has_eol, pool); SVN_ERR(svn_diff_mem_string_diff(&diff, orig, val, &options, pool)); @@ -888,6 +898,12 @@ display_prop_diffs(const apr_array_heade svn_dirent_local_style(path, pool), svn_cmdline_output_encoding(pool), orig, val, pool)); + if (!val_has_eol) + { + const char *s = "\\ No newline at end of property" APR_EOL_STR; + apr_size_t len = strlen(s); + SVN_ERR(svn_stream_write(out, s, &len)); + } } } return svn_cmdline_fflush(stdout); Modified: subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/depth_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/depth_tests.py?rev=1207512&r1=1207511&r2=1207512&view=diff ============================================================================== --- subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/depth_tests.py (original) +++ subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/depth_tests.py Mon Nov 28 19:06:34 2011 @@ -1076,7 +1076,8 @@ def diff_in_depthy_wc(sbox): "___________________________________________________________________\n", "Deleted: foo\n", "## -1 +0,0 ##\n", - "-foo-val\n"] + "-foo-val\n", + "\\ No newline at end of property\n"] os.chdir(wc_empty) Modified: subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/diff_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/diff_tests.py?rev=1207512&r1=1207511&r2=1207512&view=diff ============================================================================== --- subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/diff_tests.py (original) +++ subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/diff_tests.py Mon Nov 28 19:06:34 2011 @@ -143,6 +143,47 @@ def make_git_diff_header(target_path, re ] return output +def make_diff_prop_header(path): + """Return a property diff sub-header, as a list of newline-terminated + strings.""" + return [ + "\n", + "Property changes on: " + path.replace('\\', '/') + "\n", + "___________________________________________________________________\n" + ] + +def make_diff_prop_val(plus_minus, pval): + "Return diff for prop value PVAL, with leading PLUS_MINUS (+ or -)." + if len(pval) > 0 and pval[-1] != '\n': + return [plus_minus + pval + "\n","\\ No newline at end of property\n"] + return [plus_minus + pval] + +def make_diff_prop_deleted(pname, pval): + """Return a property diff for deletion of property PNAME, old value PVAL. + PVAL is a single string with no embedded newlines. Return the result + as a list of newline-terminated strings.""" + return [ + "Deleted: " + pname + "\n", + "## -1 +0,0 ##\n" + ] + make_diff_prop_val("-", pval) + +def make_diff_prop_added(pname, pval): + """Return a property diff for addition of property PNAME, new value PVAL. + PVAL is a single string with no embedded newlines. Return the result + as a list of newline-terminated strings.""" + return [ + "Added: " + pname + "\n", + "## -0,0 +1 ##\n", + ] + make_diff_prop_val("+", pval) + +def make_diff_prop_modified(pname, pval1, pval2): + """Return a property diff for modification of property PNAME, old value + PVAL1, new value PVAL2. PVAL is a single string with no embedded + newlines. Return the result as a list of newline-terminated strings.""" + return [ + "Modified: " + pname + "\n", + "## -1 +1 ##\n", + ] + make_diff_prop_val("-", pval1) + make_diff_prop_val("+", pval2) ###################################################################### # Diff output checker @@ -734,29 +775,20 @@ def diff_only_property_change(sbox): sbox.build() wc_dir = sbox.wc_dir - expected_output = [ - "Index: iota\n", - "===================================================================\n", - "--- iota\t(revision 1)\n", - "+++ iota\t(revision 2)\n", - "\n", - "Property changes on: iota\n", - "___________________________________________________________________\n", - "Added: svn:eol-style\n", - "## -0,0 +1 ##\n", - "+native\n" ] - - expected_reverse_output = list(expected_output) - expected_reverse_output[2] = expected_reverse_output[2].replace("1", "2") - expected_reverse_output[3] = expected_reverse_output[3].replace("2", "1") - expected_reverse_output[7] = expected_reverse_output[7].replace("Added", - "Deleted") - expected_reverse_output[8] = "## -1 +0,0 ##\n" - expected_reverse_output[9] = "-native\n" - - expected_rev1_output = list(expected_output) - expected_rev1_output[3] = expected_rev1_output[3].replace("revision 2", - "working copy") + expected_output = \ + make_diff_header("iota", "revision 1", "revision 2") + \ + make_diff_prop_header("iota") + \ + make_diff_prop_added("svn:eol-style", "native") + + expected_reverse_output = \ + make_diff_header("iota", "revision 2", "revision 1") + \ + make_diff_prop_header("iota") + \ + make_diff_prop_deleted("svn:eol-style", "native") + + expected_rev1_output = \ + make_diff_header("iota", "revision 1", "working copy") + \ + make_diff_prop_header("iota") + \ + make_diff_prop_added("svn:eol-style", "native") os.chdir(sbox.wc_dir) svntest.actions.run_and_verify_svn(None, None, [], @@ -2015,33 +2047,17 @@ def diff_property_changes_to_base(sbox): wc_dir = sbox.wc_dir - add_diff = [ - "\n", - "Property changes on: A\n", - "___________________________________________________________________\n", - "Added: dirprop\n", - "## -0,0 +1 ##\n", - "+r2value\n", - "\n", - "Property changes on: iota\n", - "___________________________________________________________________\n", - "Added: fileprop\n", - "## -0,0 +1 ##\n", - "+r2value\n"] - - del_diff = [ - "\n", - "Property changes on: A\n", - "___________________________________________________________________\n", - "Deleted: dirprop\n", - "## -1 +0,0 ##\n", - "-r2value\n", - "\n", - "Property changes on: iota\n", - "___________________________________________________________________\n", - "Deleted: fileprop\n", - "## -1 +0,0 ##\n", - "-r2value\n"] + add_diff = \ + make_diff_prop_header("A") + \ + make_diff_prop_added("dirprop", "r2value") + \ + make_diff_prop_header("iota") + \ + make_diff_prop_added("fileprop", "r2value") + + del_diff = \ + make_diff_prop_header("A") + \ + make_diff_prop_deleted("dirprop", "r2value") + \ + make_diff_prop_header("iota") + \ + make_diff_prop_deleted("fileprop", "r2value") expected_output_r1_r2 = list(make_diff_header('A', 'revision 1', 'revision 2') @@ -2277,35 +2293,15 @@ def diff_prop_change_local_propmod(sbox) sbox.build() - expected_output_r2_wc = [ - "Index: A\n", - "===================================================================\n", - "--- A\t(revision 2)\n", - "+++ A\t(working copy)\n", - "\n", - "Property changes on: A\n", - "___________________________________________________________________\n", - "Modified: dirprop\n", - "## -1 +1 ##\n", - "-r2value\n", - "+workingvalue\n", - "Added: newdirprop\n", - "## -0,0 +1 ##\n", - "+newworkingvalue\n", - "Index: iota\n", - "===================================================================\n", - "--- iota\t(revision 2)\n", - "+++ iota\t(working copy)\n", - "\n", - "Property changes on: iota\n", - "___________________________________________________________________\n", - "Modified: fileprop\n", - "## -1 +1 ##\n", - "-r2value\n", - "+workingvalue\n", - "Added: newfileprop\n", - "## -0,0 +1 ##\n", - "+newworkingvalue\n" ] + expected_output_r2_wc = \ + make_diff_header("A", "revision 2", "working copy") + \ + make_diff_prop_header("A") + \ + make_diff_prop_modified("dirprop", "r2value", "workingvalue") + \ + make_diff_prop_added("newdirprop", "newworkingvalue") + \ + make_diff_header("iota", "revision 2", "working copy") + \ + make_diff_prop_header("iota") + \ + make_diff_prop_modified("fileprop", "r2value", "workingvalue") + \ + make_diff_prop_added("newfileprop", "newworkingvalue") os.chdir(sbox.wc_dir) @@ -2368,31 +2364,16 @@ def diff_repos_wc_add_with_props(sbox): diff_foo = [ "@@ -0,0 +1 @@\n", "+content\n", - "\n", - "Property changes on: foo\n", - "___________________________________________________________________\n", - "Added: propname\n", - "## -0,0 +1 ##\n", - "+propvalue\n", - ] - diff_X = [ - "\n", - "Property changes on: X\n", - "___________________________________________________________________\n", - "Added: propname\n", - "## -0,0 +1 ##\n", - "+propvalue\n", - ] + ] + make_diff_prop_header("foo") + \ + make_diff_prop_added("propname", "propvalue") + diff_X = \ + make_diff_prop_header("X") + \ + make_diff_prop_added("propname", "propvalue") diff_X_bar = [ "@@ -0,0 +1 @@\n", "+content\n", - "\n", - "Property changes on: X/bar\n", - "___________________________________________________________________\n", - "Added: propname\n", - "## -0,0 +1 ##\n", - "+propvalue\n", - ] + ] + make_diff_prop_header("X/bar") + \ + make_diff_prop_added("propname", "propvalue") diff_X_r1_base = make_diff_header("X", "revision 1", "working copy") + diff_X @@ -2866,49 +2847,32 @@ def diff_with_depth(sbox): sbox.build() B_path = os.path.join('A', 'B') - diff = [ - "\n", - "Property changes on: .\n", - "___________________________________________________________________\n", - "Added: foo1\n", - "## -0,0 +1 ##\n", - "+bar1\n", - "\n", - "Property changes on: iota\n", - "___________________________________________________________________\n", - "Added: foo2\n", - "## -0,0 +1 ##\n", - "+bar2\n", - "\n", - "Property changes on: A\n", - "___________________________________________________________________\n", - "Added: foo3\n", - "## -0,0 +1 ##\n", - "+bar3\n", - "\n", - "Property changes on: A/B\n", - "___________________________________________________________________\n", - "Added: foo4\n", - "## -0,0 +1 ##\n", - "+bar4\n"] + diff = make_diff_prop_header(".") + \ + make_diff_prop_added("foo1", "bar1") + \ + make_diff_prop_header("iota") + \ + make_diff_prop_added("foo2", "bar2") + \ + make_diff_prop_header("A") + \ + make_diff_prop_added("foo3", "bar3") + \ + make_diff_prop_header("A/B") + \ + make_diff_prop_added("foo4", "bar4") dot_header = make_diff_header(".", "revision 1", "working copy") iota_header = make_diff_header('iota', "revision 1", "working copy") A_header = make_diff_header('A', "revision 1", "working copy") B_header = make_diff_header(B_path, "revision 1", "working copy") - expected_empty = svntest.verify.UnorderedOutput(dot_header + diff[:6]) - expected_files = svntest.verify.UnorderedOutput(dot_header + diff[:6] - + iota_header + diff[7:12]) - expected_immediates = svntest.verify.UnorderedOutput(dot_header + diff[:6] + expected_empty = svntest.verify.UnorderedOutput(dot_header + diff[:7]) + expected_files = svntest.verify.UnorderedOutput(dot_header + diff[:7] + + iota_header + diff[8:14]) + expected_immediates = svntest.verify.UnorderedOutput(dot_header + diff[:7] + iota_header - + diff[7:12] - + A_header + diff[8:18]) - expected_infinity = svntest.verify.UnorderedOutput(dot_header + diff[:6] + + diff[8:14] + + A_header + diff[15:21]) + expected_infinity = svntest.verify.UnorderedOutput(dot_header + diff[:7] + iota_header - + diff[7:12] - + A_header + diff[8:18] - + B_header + diff[12:]) + + diff[8:14] + + A_header + diff[15:21] + + B_header + diff[22:]) os.chdir(sbox.wc_dir) @@ -2944,18 +2908,18 @@ def diff_with_depth(sbox): A_header = make_diff_header('A', "revision 1", "revision 2") B_header = make_diff_header(B_path, "revision 1", "revision 2") - expected_empty = svntest.verify.UnorderedOutput(dot_header + diff[:6]) - expected_files = svntest.verify.UnorderedOutput(dot_header + diff[:6] - + iota_header + diff[7:12]) - expected_immediates = svntest.verify.UnorderedOutput(dot_header + diff[:6] + expected_empty = svntest.verify.UnorderedOutput(dot_header + diff[:7]) + expected_files = svntest.verify.UnorderedOutput(dot_header + diff[:7] + + iota_header + diff[8:14]) + expected_immediates = svntest.verify.UnorderedOutput(dot_header + diff[:7] + iota_header - + diff[7:12] - + A_header + diff[8:18]) + + diff[8:14] + + A_header + diff[15:21]) expected_infinity = svntest.verify.UnorderedOutput(dot_header + diff[:6] + iota_header - + diff[7:12] - + A_header + diff[8:18] - + B_header + diff[12:]) + + diff[8:14] + + A_header + diff[15:21] + + B_header + diff[22:]) # Test repos-repos diff. svntest.actions.run_and_verify_svn(None, expected_empty, [], @@ -2967,66 +2931,31 @@ def diff_with_depth(sbox): svntest.actions.run_and_verify_svn(None, expected_infinity, [], 'diff', '-c2', '--depth', 'infinity') - diff_wc_repos = [ - "Index: A/B\n", - "===================================================================\n", - "--- A/B\t(revision 2)\n", - "+++ A/B\t(working copy)\n", - "\n", - "Property changes on: A/B\n", - "___________________________________________________________________\n", - "Modified: foo4\n", - "## -1 +1 ##\n", - "-bar4\n", - "+baz4\n", - "Index: A\n", - "===================================================================\n", - "--- A\t(revision 2)\n", - "+++ A\t(working copy)\n", - "\n", - "Property changes on: A\n", - "___________________________________________________________________\n", - "Modified: foo3\n", - "## -1 +1 ##\n", - "-bar3\n", - "+baz3\n", - "Index: A/mu\n", - "===================================================================\n", - "--- A/mu\t(revision 1)\n", - "+++ A/mu\t(working copy)\n", + diff_wc_repos = \ + make_diff_header("A/B", "revision 2", "working copy") + \ + make_diff_prop_header("A/B") + \ + make_diff_prop_modified("foo4", "bar4", "baz4") + \ + make_diff_header("A", "revision 2", "working copy") + \ + make_diff_prop_header("A") + \ + make_diff_prop_modified("foo3", "bar3", "baz3") + \ + make_diff_header("A/mu", "revision 1", "working copy") + [ "@@ -1 +1,2 @@\n", " This is the file 'mu'.\n", "+new text\n", - "Index: iota\n", - "===================================================================\n", - "--- iota\t(revision 2)\n", - "+++ iota\t(working copy)\n", + ] + make_diff_header("iota", "revision 2", "working copy") + [ "@@ -1 +1,2 @@\n", " This is the file 'iota'.\n", "+new text\n", - "\n", - "Property changes on: iota\n", - "___________________________________________________________________\n", - "Modified: foo2\n", - "## -1 +1 ##\n", - "-bar2\n", - "+baz2\n", - "Index: .\n", - "===================================================================\n", - "--- .\t(revision 2)\n", - "+++ .\t(working copy)\n", - "\n", - "Property changes on: .\n", - "___________________________________________________________________\n", - "Modified: foo1\n", - "## -1 +1 ##\n", - "-bar1\n", - "+baz1\n" ] - - expected_empty = svntest.verify.UnorderedOutput(diff_wc_repos[43:]) - expected_files = svntest.verify.UnorderedOutput(diff_wc_repos[29:]) - expected_immediates = svntest.verify.UnorderedOutput(diff_wc_repos[11:22] - +diff_wc_repos[29:]) + ] + make_diff_prop_header("iota") + \ + make_diff_prop_modified("foo2", "bar2", "baz2") + \ + make_diff_header(".", "revision 2", "working copy") + \ + make_diff_prop_header(".") + \ + make_diff_prop_modified("foo1", "bar1", "baz1") + + expected_empty = svntest.verify.UnorderedOutput(diff_wc_repos[49:]) + expected_files = svntest.verify.UnorderedOutput(diff_wc_repos[33:]) + expected_immediates = svntest.verify.UnorderedOutput(diff_wc_repos[13:26] + +diff_wc_repos[33:]) expected_infinity = svntest.verify.UnorderedOutput(diff_wc_repos[:]) svntest.actions.run_and_verify_svn(None, None, [], @@ -3539,10 +3468,8 @@ def diff_prop_missing_context(sbox): svntest.main.run_svn(None, "propset", "prop", prop_val, iota_path) expected_output = make_diff_header(iota_path, 'revision 2', - 'working copy') + [ - "\n", - "Property changes on: %s\n" % iota_path.replace('\\', '/'), - "___________________________________________________________________\n", + 'working copy') + \ + make_diff_prop_header(iota_path) + [ "Modified: prop\n", "## -1,7 +1,4 ##\n", "-line 1\n", @@ -3609,10 +3536,8 @@ def diff_prop_multiple_hunks(sbox): svntest.main.run_svn(None, "propset", "prop", prop_val, iota_path) expected_output = make_diff_header(iota_path, 'revision 2', - 'working copy') + [ - "\n", - "Property changes on: %s\n" % iota_path.replace('\\', '/'), - "___________________________________________________________________\n", + 'working copy') + \ + make_diff_prop_header(iota_path) + [ "Modified: prop\n", "## -1,6 +1,7 ##\n", " line 1\n", @@ -3694,24 +3619,16 @@ def diff_git_with_props(sbox): svntest.main.run_svn(None, 'propset', 'svn:eol-style', 'native', new_path) svntest.main.run_svn(None, 'propset', 'svn:keywords', 'Id', iota_path) - expected_output = make_git_diff_header(new_path, "new", "revision 0", - "working copy", - add=True, text_changes=False) + [ - "\n", - "Property changes on: new\n", - "___________________________________________________________________\n", - "Added: svn:eol-style\n", - "## -0,0 +1 ##\n", - "+native\n", - ] + make_git_diff_header(iota_path, "iota", "revision 1", "working copy", - text_changes=False) + [ - "\n", - "Property changes on: iota\n", - "___________________________________________________________________\n", - "Added: svn:keywords\n", - "## -0,0 +1 ##\n", - "+Id\n", - ] + expected_output = make_git_diff_header(new_path, "new", + "revision 0", "working copy", + add=True, text_changes=False) + \ + make_diff_prop_header("new") + \ + make_diff_prop_added("svn:eol-style", "native") + \ + make_git_diff_header(iota_path, "iota", + "revision 1", "working copy", + text_changes=False) + \ + make_diff_prop_header("iota") + \ + make_diff_prop_added("svn:keywords", "Id") svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff', '--git', wc_dir) @@ -3739,14 +3656,9 @@ def diff_git_with_props_on_dir(sbox): os.chdir(wc_dir) expected_output = make_git_diff_header(".", "", "revision 1", "revision 2", - add=False, text_changes=False) + [ - "\n", - "Property changes on: \n", - "___________________________________________________________________\n", - "Added: a\n", - "## -0,0 +1 ##\n", - "+b\n", - ] + add=False, text_changes=False) + \ + make_diff_prop_header("") + \ + make_diff_prop_added("a", "b") svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff', '-c2', '--git') Modified: subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/patch_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/patch_tests.py?rev=1207512&r1=1207511&r2=1207512&view=diff ============================================================================== --- subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/patch_tests.py (original) +++ subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/patch_tests.py Mon Nov 28 19:06:34 2011 @@ -3427,7 +3427,6 @@ def patch_strip_cwd(sbox): "patch --strip propchanges cwd" return patch_one_property(sbox, True) -@XFail() @Issue(3814) def patch_set_prop_no_eol(sbox): "patch doesn't append newline to properties" @@ -3805,6 +3804,59 @@ def patch_delete_and_skip(sbox): 1, # check-props 1) # dry-run +@Issue(3991) +def patch_lacking_trailing_eol(sbox): + "patch file lacking trailing eol" + sbox.build(read_only = True) + wc_dir = sbox.wc_dir + + patch_file_path = make_patch_path(sbox) + iota_path = os.path.join(wc_dir, 'iota') + mu_path = os.path.join(wc_dir, 'A', 'mu') + + # Prepare + expected_status = svntest.actions.get_virginal_state(wc_dir, 1) + + # Apply patch + unidiff_patch = [ + "Index: iota\n", + "===================================================================\n", + "--- iota\t(revision 1)\n", + "+++ iota\t(working copy)\n", + # TODO: -1 +1 + "@@ -1 +1,2 @@\n", + " This is the file 'iota'.\n", + "+Some more bytes", # No trailing \n on this line! + ] + + svntest.main.file_write(patch_file_path, ''.join(unidiff_patch)) + + gamma_contents = "It is the file 'gamma'.\n" + iota_contents = "This is the file 'iota'.\n" + new_contents = "new\n" + + expected_output = [ + 'U %s\n' % os.path.join(wc_dir, 'iota'), + ] + + # Expect a newline to be appended + expected_disk = svntest.main.greek_state.copy() + expected_disk.tweak('iota', contents=iota_contents + "Some more bytes") + + expected_status = svntest.actions.get_virginal_state(wc_dir, 1) + expected_status.tweak('iota', status='M ') + + expected_skip = wc.State('', { }) + + svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path), + expected_output, + expected_disk, + expected_status, + expected_skip, + None, # expected err + 1, # check-props + 1) # dry-run + ######################################################################## #Run the tests @@ -3845,6 +3897,7 @@ test_list = [ None, patch_reversed_add_with_props2, patch_dev_null, patch_delete_and_skip, + patch_lacking_trailing_eol, ] if __name__ == '__main__': Modified: subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/special_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/special_tests.py?rev=1207512&r1=1207511&r2=1207512&view=diff ============================================================================== --- subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/special_tests.py (original) +++ subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/cmdline/special_tests.py Mon Nov 28 19:06:34 2011 @@ -551,7 +551,9 @@ def diff_symlink_to_dir(sbox): "___________________________________________________________________\n", "Added: svn:special\n", "## -0,0 +1 ##\n", - "+*\n" ] + "+*\n", + "\\ No newline at end of property\n" + ] svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff', '.') # We should get the same output if we the diff the symlink itself. Modified: subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/libsvn_diff/parse-diff-test.c URL: http://svn.apache.org/viewvc/subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/libsvn_diff/parse-diff-test.c?rev=1207512&r1=1207511&r2=1207512&view=diff ============================================================================== --- subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/libsvn_diff/parse-diff-test.c (original) +++ subversion/branches/1.7.x-svn-patch-eol-fixes/subversion/tests/libsvn_diff/parse-diff-test.c Mon Nov 28 19:06:34 2011 @@ -246,29 +246,38 @@ static const char *bad_git_diff_header = "diff --git a/ b/path 1 b/ b/path 1" NL "new file mode 100644" NL; +static const char *unidiff_lacking_trailing_eol = + "Index: A/C/gamma" NL + "===================================================================" NL + "--- A/C/gamma\t(revision 2)" NL + "+++ A/C/gamma\t(working copy)" NL + "@@ -1 +1,2 @@" NL + " This is the file 'gamma'." NL + "+some more bytes to 'gamma'"; /* Don't add NL after this line */ -/* Create a PATCH_FILE with name FNAME containing the contents of DIFF. */ + +/* Create a PATCH_FILE containing the contents of DIFF. */ static svn_error_t * -create_patch_file(svn_patch_file_t **patch_file, const char *fname, +create_patch_file(svn_patch_file_t **patch_file, const char *diff, apr_pool_t *pool) { + apr_size_t bytes; apr_size_t len; - apr_status_t status; + const char *path; apr_file_t *apr_file; /* Create a patch file. */ - status = apr_file_open(&apr_file, fname, - (APR_READ | APR_WRITE | APR_CREATE | APR_TRUNCATE | - APR_DELONCLOSE), APR_OS_DEFAULT, pool); - if (status != APR_SUCCESS) - return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "Cannot open '%s'", - fname); - len = strlen(diff); - status = apr_file_write_full(apr_file, diff, len, &len); - if (status || len != strlen(diff)) + SVN_ERR(svn_io_open_unique_file3(&apr_file, &path, NULL, + svn_io_file_del_on_pool_cleanup, + pool, pool)); + + bytes = strlen(diff); + SVN_ERR(svn_io_file_write_full(apr_file, diff, bytes, &len, pool)); + if (len != bytes) return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, - "Cannot write to '%s'", fname); - SVN_ERR(svn_diff_open_patch_file(patch_file, fname, pool)); + "Cannot write to '%s'", path); + SVN_ERR(svn_io_file_close(apr_file, pool)); + SVN_ERR(svn_diff_open_patch_file(patch_file, path, pool)); return SVN_NO_ERROR; } @@ -305,7 +314,8 @@ check_content(svn_diff_hunk_t *hunk, svn SVN_TEST_STRING_ASSERT(exp_buf->data, hunk_buf->data); } - SVN_TEST_ASSERT(hunk_buf->len == 0); + if (!hunk_eof) + SVN_TEST_ASSERT(hunk_buf->len == 0); return SVN_NO_ERROR; } @@ -314,7 +324,6 @@ static svn_error_t * test_parse_unidiff(apr_pool_t *pool) { svn_patch_file_t *patch_file; - const char *fname = "test_parse_unidiff.patch"; svn_boolean_t reverse; svn_boolean_t ignore_whitespace; int i; @@ -330,7 +339,7 @@ test_parse_unidiff(apr_pool_t *pool) svn_pool_clear(iterpool); - SVN_ERR(create_patch_file(&patch_file, fname, unidiff, pool)); + SVN_ERR(create_patch_file(&patch_file, unidiff, pool)); /* We have two patches with one hunk each. * Parse the first patch. */ @@ -393,9 +402,8 @@ test_parse_git_diff(apr_pool_t *pool) svn_patch_file_t *patch_file; svn_patch_t *patch; svn_diff_hunk_t *hunk; - const char *fname = "test_parse_git_diff.patch"; - SVN_ERR(create_patch_file(&patch_file, fname, git_unidiff, pool)); + SVN_ERR(create_patch_file(&patch_file, git_unidiff, pool)); /* Parse a deleted empty file */ SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, @@ -467,10 +475,8 @@ test_parse_git_tree_and_text_diff(apr_po svn_patch_file_t *patch_file; svn_patch_t *patch; svn_diff_hunk_t *hunk; - const char *fname = "test_parse_git_tree_and_text_diff.patch"; - SVN_ERR(create_patch_file(&patch_file, fname, git_tree_and_text_unidiff, - pool)); + SVN_ERR(create_patch_file(&patch_file, git_tree_and_text_unidiff, pool)); /* Parse a copied file with text modifications. */ SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, @@ -567,10 +573,8 @@ test_bad_git_diff_headers(apr_pool_t *po svn_patch_file_t *patch_file; svn_patch_t *patch; svn_diff_hunk_t *hunk; - const char *fname = "test_bad_git_diff_header.patch"; - SVN_ERR(create_patch_file(&patch_file, fname, bad_git_diff_header, - pool)); + SVN_ERR(create_patch_file(&patch_file, bad_git_diff_header, pool)); SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, FALSE, /* reverse */ @@ -607,9 +611,8 @@ test_parse_property_diff(apr_pool_t *poo svn_prop_patch_t *prop_patch; svn_diff_hunk_t *hunk; apr_array_header_t *hunks; - const char *fname = "test_parse_property_diff.patch"; - SVN_ERR(create_patch_file(&patch_file, fname, property_unidiff, pool)); + SVN_ERR(create_patch_file(&patch_file, property_unidiff, pool)); SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, FALSE, /* reverse */ @@ -710,10 +713,8 @@ test_parse_property_and_text_diff(apr_po svn_prop_patch_t *prop_patch; svn_diff_hunk_t *hunk; apr_array_header_t *hunks; - const char *fname = "test_parse_property_and_text_diff.patch"; - SVN_ERR(create_patch_file(&patch_file, fname, property_and_text_unidiff, - pool)); + SVN_ERR(create_patch_file(&patch_file, property_and_text_unidiff, pool)); SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, FALSE, /* reverse */ @@ -766,10 +767,8 @@ test_parse_diff_symbols_in_prop_unidiff( svn_prop_patch_t *prop_patch; svn_diff_hunk_t *hunk; apr_array_header_t *hunks; - const char *fname = "test_parse_diff_symbols_in_prop_unidiff.patch"; - SVN_ERR(create_patch_file(&patch_file, fname, diff_symbols_in_prop_unidiff, - pool)); + SVN_ERR(create_patch_file(&patch_file, diff_symbols_in_prop_unidiff, pool)); SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, FALSE, /* reverse */ @@ -865,10 +864,8 @@ test_git_diffs_with_spaces_diff(apr_pool { svn_patch_file_t *patch_file; svn_patch_t *patch; - const char *fname = "test_git_diffs_with_spaces_diff.patch"; - SVN_ERR(create_patch_file(&patch_file, fname, path_with_spaces_unidiff, - pool)); + SVN_ERR(create_patch_file(&patch_file, path_with_spaces_unidiff, pool)); SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, FALSE, /* reverse */ @@ -913,6 +910,55 @@ test_git_diffs_with_spaces_diff(apr_pool SVN_ERR(svn_diff_close_patch_file(patch_file, pool)); return SVN_NO_ERROR; } + +static svn_error_t * +test_parse_unidiff_lacking_trailing_eol(apr_pool_t *pool) +{ + svn_patch_file_t *patch_file; + svn_boolean_t reverse; + svn_boolean_t ignore_whitespace; + int i; + apr_pool_t *iterpool; + + reverse = FALSE; + ignore_whitespace = FALSE; + iterpool = svn_pool_create(pool); + for (i = 0; i < 2; i++) + { + svn_patch_t *patch; + svn_diff_hunk_t *hunk; + + svn_pool_clear(iterpool); + + SVN_ERR(create_patch_file(&patch_file, unidiff_lacking_trailing_eol, + pool)); + + /* We have one patch with one hunk. Parse it. */ + SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, reverse, + ignore_whitespace, iterpool, + iterpool)); + SVN_TEST_ASSERT(patch); + SVN_TEST_STRING_ASSERT(patch->old_filename, "A/C/gamma"); + SVN_TEST_STRING_ASSERT(patch->new_filename, "A/C/gamma"); + SVN_TEST_ASSERT(patch->hunks->nelts == 1); + + hunk = APR_ARRAY_IDX(patch->hunks, 0, svn_diff_hunk_t *); + SVN_ERR(check_content(hunk, ! reverse, + "This is the file 'gamma'." NL, + pool)); + + SVN_ERR(check_content(hunk, reverse, + "This is the file 'gamma'." NL + "some more bytes to 'gamma'", + pool)); + + reverse = !reverse; + SVN_ERR(svn_diff_close_patch_file(patch_file, pool)); + } + svn_pool_destroy(iterpool); + return SVN_NO_ERROR; +} + /* ========================================================================== */ struct svn_test_descriptor_t test_funcs[] = @@ -934,5 +980,7 @@ struct svn_test_descriptor_t test_funcs[ "test property diffs with odd symbols"), SVN_TEST_PASS2(test_git_diffs_with_spaces_diff, "test git diffs with spaces in paths"), + SVN_TEST_PASS2(test_parse_unidiff_lacking_trailing_eol, + "test parsing unidiffs lacking trailing eol"), SVN_TEST_NULL };