Author: stsp
Date: Sat Nov 26 20:18:33 2011
New Revision: 1206576
URL: http://svn.apache.org/viewvc?rev=1206576&view=rev
Log:
For issue #3814 ("patch doesn't append newline to properties"), make
svn diff output a marker line "\ No newline at end of property" if
a property value doesn't end in a newline.
This will later allow 'svn patch' to create properties both with a
trailing newline (e.g. svn:mergeinfo) and without a trailing newline
(e.g. svn:eol-style).
* subversion/libsvn_client/diff.c
(maybe_append_eol): Add output parameter had_eol, which tells the
caller whether the property value ended with an EOL sequence.
(display_prop_diffs): If the property value does not end with an EOL
sequence append the line "\ No newline at end of property".
* subversion/svnlook/main.c
(maybe_append_eol, display_prop_diffs): Same changes as libsvn_client/diff.c.
For some reason this code is duplicated here.
* subversion/tests/cmdline/depth_tests.py
(diff_in_depthy_wc): Adjust test expectations.
* subversion/tests/cmdline/diff_tests.py
(make_diff_prop_val): New helper.
(make_diff_prop_deleted, make_diff_prop_added,
make_diff_prop_modified): Use the new helper function to create correct
expected output for property diffs.
(diff_with_depth): Adjust expected output.
* subversion/tests/cmdline/special_tests.py
(diff_symlink_to_dir): Adjust expected output.
Modified:
subversion/trunk/subversion/libsvn_client/diff.c
subversion/trunk/subversion/svnlook/main.c
subversion/trunk/subversion/tests/cmdline/depth_tests.py
subversion/trunk/subversion/tests/cmdline/diff_tests.py
subversion/trunk/subversion/tests/cmdline/special_tests.py
Modified: subversion/trunk/subversion/libsvn_client/diff.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/diff.c?rev=1206576&r1=1206575&r2=1206576&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/diff.c (original)
+++ subversion/trunk/subversion/libsvn_client/diff.c Sat Nov 26 20:18:33 2011
@@ -147,18 +147,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')
@@ -167,6 +174,8 @@ maybe_append_eol(const svn_string_t *tok
}
else
{
+ if (had_eol)
+ *had_eol = TRUE;
return token;
}
}
@@ -665,18 +674,19 @@ 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_empty(iterpool);
- orig = maybe_append_eol(tmp, iterpool);
+ orig = maybe_append_eol(tmp, NULL, iterpool);
tmp = propchange->value ? propchange->value :
svn_string_create_empty(iterpool);
- val = maybe_append_eol(tmp, iterpool);
+ val = maybe_append_eol(tmp, &val_has_eol, iterpool);
SVN_ERR(svn_diff_mem_string_diff(&diff, orig, val, &options,
iterpool));
@@ -695,7 +705,12 @@ display_prop_diffs(const apr_array_heade
svn_dirent_local_style(path,
iterpool),
encoding, orig, val, iterpool));
-
+ 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(outstream, s, &len));
+ }
}
}
svn_pool_destroy(iterpool);
Modified: subversion/trunk/subversion/svnlook/main.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/svnlook/main.c?rev=1206576&r1=1206575&r2=1206576&view=diff
==============================================================================
--- subversion/trunk/subversion/svnlook/main.c (original)
+++ subversion/trunk/subversion/svnlook/main.c Sat Nov 26 20:18:33 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_empty(pool);
- orig = maybe_append_eol(tmp, pool);
+ orig = maybe_append_eol(tmp, NULL, pool);
tmp = pc->value ? pc->value :
svn_string_create_empty(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/trunk/subversion/tests/cmdline/depth_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/depth_tests.py?rev=1206576&r1=1206575&r2=1206576&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/depth_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/depth_tests.py Sat Nov 26
20:18:33 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/trunk/subversion/tests/cmdline/diff_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/diff_tests.py?rev=1206576&r1=1206575&r2=1206576&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/diff_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/diff_tests.py Sat Nov 26 20:18:33
2011
@@ -146,15 +146,20 @@ def make_diff_prop_header(path):
"___________________________________________________________________\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",
- "-" + pval + "\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.
@@ -163,8 +168,7 @@ def make_diff_prop_added(pname, pval):
return [
"Added: " + pname + "\n",
"## -0,0 +1 ##\n",
- "+" + pval + "\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
@@ -173,9 +177,7 @@ def make_diff_prop_modified(pname, pval1
return [
"Modified: " + pname + "\n",
"## -1 +1 ##\n",
- "-" + pval1 + "\n",
- "+" + pval2 + "\n"
- ]
+ ] + make_diff_prop_val("-", pval1) + make_diff_prop_val("+", pval2)
######################################################################
# Diff output checker
@@ -2853,18 +2855,18 @@ def diff_with_depth(sbox):
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)
@@ -2900,18 +2902,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, [],
@@ -2944,10 +2946,10 @@ def diff_with_depth(sbox):
make_diff_prop_header(".") + \
make_diff_prop_modified("foo1", "bar1", "baz1")
- 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:])
+ 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, [],
Modified: subversion/trunk/subversion/tests/cmdline/special_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/special_tests.py?rev=1206576&r1=1206575&r2=1206576&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/special_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/special_tests.py Sat Nov 26
20:18:33 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.