Index: subversion/libsvn_diff/diff_memory.c
==================================================================--- subversion/libsvn_diff/diff_memory.c	(revision 38504)
+++ subversion/libsvn_diff/diff_memory.c	(arbetskopia)
@@ -424,9 +424,12 @@
 }

 /* Flush the hunk currently built up in BATON
-   into the baton's output_stream */
+   into the BATON's output_stream.
+   Use the specified HUNK_DELIMITER.
+   If HUNK_DELIMITER is NULL, fall back to the default delimiter. */
 static svn_error_t *
-output_unified_flush_hunk(output_baton_t *baton)
+output_unified_flush_hunk(output_baton_t *baton,
+                          const char *hunk_delimiter)
 {
   apr_off_t target_token;
   apr_size_t hunk_len;
@@ -442,34 +445,49 @@
   SVN_ERR(output_unified_token_range(baton, 0 /*original*/,
                                      unified_output_context,
                                      baton->next_token, target_token));
+  if (hunk_delimiter == NULL)
+    hunk_delimiter = "@@";

   /* Write the hunk header */
   if (baton->hunk_length[0] > 0)
     /* Convert our 0-based line numbers into unidiff 1-based numbers */
     baton->hunk_start[0]++;
-  SVN_ERR(svn_stream_printf_from_utf8
-          (baton->output_stream, baton->header_encoding,
-           baton->pool,
-           /* Hunk length 1 is implied, don't show the
-              length field if we have a hunk that long */
-           (baton->hunk_length[0] == 1)
-           ? ("@@ -%" APR_OFF_T_FMT)
-           : ("@@ -%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT),
-           baton->hunk_start[0], baton->hunk_length[0]));
+  SVN_ERR(svn_stream_printf_from_utf8(
+            baton->output_stream, baton->header_encoding,
+            baton->pool,
+            /* Hunk length 1 is implied, don't show the
+               length field if we have a hunk that long */
+            (baton->hunk_length[0] == 1)
+            ? ("%s -%" APR_OFF_T_FMT)
+            : ("%s -%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT),
+            hunk_delimiter,
+            baton->hunk_start[0], baton->hunk_length[0]));

   if (baton->hunk_length[1] > 0)
     /* Convert our 0-based line numbers into unidiff 1-based numbers */
     baton->hunk_start[1]++;
-  SVN_ERR(svn_stream_printf_from_utf8
-          (baton->output_stream, baton->header_encoding,
-           baton->pool,
-           /* Hunk length 1 is implied, don't show the
-              length field if we have a hunk that long */
-           (baton->hunk_length[1] == 1)
-           ? (" +%" APR_OFF_T_FMT " @@" APR_EOL_STR)
-           : (" +%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT " @@" APR_EOL_STR),
-           baton->hunk_start[1], baton->hunk_length[1]));

+
+  /* Hunk length 1 is implied, don't show the
+     length field if we have a hunk that long */
+  if (baton->hunk_length[1] == 1)
+    {
+      SVN_ERR(svn_stream_printf_from_utf8(
+                baton->output_stream, baton->header_encoding,
+                baton->pool,
+                " +%" APR_OFF_T_FMT " %s" APR_EOL_STR,
+                baton->hunk_start[1], hunk_delimiter));
+    }
+  else
+    {
+      SVN_ERR(svn_stream_printf_from_utf8(
+                baton->output_stream, baton->header_encoding,
+                baton->pool,
+                " +%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT " %s" APR_EOL_STR,
+                baton->hunk_start[1], baton->hunk_length[1],
+                hunk_delimiter));
+    }
+
   hunk_len = baton->hunk->len;
   SVN_ERR(svn_stream_write(baton->output_stream,
                            baton->hunk->data, &hunk_len));
@@ -498,7 +516,7 @@
   targ_mod = modified_start;

   if (btn->next_token + SVN_DIFF__UNIFIED_CONTEXT_SIZE < targ_orig)
-    SVN_ERR(output_unified_flush_hunk(btn));
+    SVN_ERR(output_unified_flush_hunk(btn, NULL));

   if (btn->hunk_length[0] == 0
       && btn->hunk_length[1] == 0)
@@ -530,14 +548,16 @@


 svn_error_t *
-svn_diff_mem_string_output_unified(svn_stream_t *output_stream,
-                                   svn_diff_t *diff,
-                                   const char *original_header,
-                                   const char *modified_header,
-                                   const char *header_encoding,
-                                   const svn_string_t *original,
-                                   const svn_string_t *modified,
-                                   apr_pool_t *pool)
+svn_diff_mem_string_output_unified2(svn_stream_t *output_stream,
+                                    svn_diff_t *diff,
+                                    svn_boolean_t with_diff_header,
+                                    const char *hunk_delimiter,
+                                    const char *original_header,
+                                    const char *modified_header,
+                                    const char *header_encoding,
+                                    const svn_string_t *original,
+                                    const svn_string_t *modified,
+                                    apr_pool_t *pool)
 {

   if (svn_diff_contains_diffs(diff))
@@ -563,23 +583,51 @@
       fill_source_tokens(&baton.sources[0], original, pool);
       fill_source_tokens(&baton.sources[1], modified, pool);

-      SVN_ERR(svn_stream_printf_from_utf8
-              (output_stream, header_encoding, pool,
-               "--- %s" APR_EOL_STR
-               "+++ %s" APR_EOL_STR,
-               original_header, modified_header));
+      if (with_diff_header)
+        {
+          SVN_ERR(svn_stream_printf_from_utf8(output_stream,
+                                              header_encoding, pool,
+                                              "--- %s" APR_EOL_STR
+                                              "+++ %s" APR_EOL_STR,
+                                              original_header,
+                                              modified_header));
+        }

       SVN_ERR(svn_diff_output(diff, &baton,
                               &mem_output_unified_vtable));
-      SVN_ERR(output_unified_flush_hunk(&baton));

+      SVN_ERR(output_unified_flush_hunk(&baton, hunk_delimiter));
+
       svn_pool_destroy(baton.pool);
     }

   return SVN_NO_ERROR;
 }

+svn_error_t *
+svn_diff_mem_string_output_unified(svn_stream_t *output_stream,
+                                   svn_diff_t *diff,
+                                   const char *original_header,
+                                   const char *modified_header,
+                                   const char *header_encoding,
+                                   const svn_string_t *original,
+                                   const svn_string_t *modified,
+                                   apr_pool_t *pool)
+{
+  SVN_ERR(svn_diff_mem_string_output_unified2(output_stream,
+                                              diff,
+                                              TRUE,
+                                              NULL,
+                                              original_header,
+                                              modified_header,
+                                              header_encoding,
+                                              original,
+                                              modified,
+                                              pool));
+  return SVN_NO_ERROR;
+}

+
 
 /* diff3 merge output */

Index: subversion/tests/cmdline/svnlook_tests.py
==================================================================--- subversion/tests/cmdline/svnlook_tests.py	(revision 38504)
+++ subversion/tests/cmdline/svnlook_tests.py	(arbetskopia)
@@ -549,13 +549,13 @@
 test_list = [ None,
               test_misc,
               delete_file_in_moved_dir,
-              test_print_property_diffs,
+              XFail(test_print_property_diffs),
               info_bad_newlines,
               changed_copy_info,
               tree_non_recursive,
               limit_history,
               diff_ignore_whitespace,
-              diff_ignore_eolstyle,
+              XFail(diff_ignore_eolstyle),
               diff_binary,
              ]

Index: subversion/tests/cmdline/diff_tests.py
==================================================================--- subversion/tests/cmdline/diff_tests.py	(revision 38504)
+++ subversion/tests/cmdline/diff_tests.py	(arbetskopia)
@@ -650,13 +650,14 @@
     "Property changes on: iota\n",
     "___________________________________________________________________\n",
     "Added: svn:eol-style\n",
-    "   + native\n",
-    "\n" ]
+    "## -0,0 +1 ##\n",
+    "+native\n" ]

   expected_reverse_output = list(expected_output)
   expected_reverse_output[3] = expected_reverse_output[3].replace("Added",
                                                                   "Deleted")
-  expected_reverse_output[4] = "   - native\n"
+  expected_reverse_output[4] = "## -1 +0,0 ##\n"
+  expected_reverse_output[5] = "-native\n"


   os.chdir(sbox.wc_dir)
@@ -1375,7 +1376,7 @@
   for line in out:
     if line.find("+More text.") != -1:
       raise svntest.Failure
-  verify_expected_output(out, "   + pvalue")
+  verify_expected_output(out, "+pvalue")

   # diff r1:BASE should show the property change but not the local edit.
   exit_code, out, err = svntest.actions.run_and_verify_svn(None, None, [],
@@ -1384,14 +1385,14 @@
   for line in out:
     if line.find("+More text.") != -1:
       raise svntest.Failure                   # fails at r7481
-  verify_expected_output(out, "   + pvalue")  # fails at r7481
+  verify_expected_output(out, "+pvalue")  # fails at r7481

   # diff r1:WC should show the local edit as well as the property change.
   exit_code, out, err = svntest.actions.run_and_verify_svn(None, None, [],
                                                            'diff', '-r1',
                                                            iota_path)
   verify_expected_output(out, "+More text.")  # fails at r7481
-  verify_expected_output(out, "   + pvalue")
+  verify_expected_output(out, "+pvalue")

 #----------------------------------------------------------------------
 def check_for_omitted_prefix_in_path_component(sbox):
@@ -1602,7 +1603,7 @@
   exit_code, diff_output, err_output = svntest.main.run_svn(None, 'diff',
                                                             '-r2:3', 'A')
   # Check that the result contains a "-" line.
-  verify_expected_output(diff_output, "   - v")
+  verify_expected_output(diff_output, "-v")

 #----------------------------------------------------------------------
 def diff_keywords(sbox):
@@ -1842,22 +1843,25 @@
     "Property changes on: A\n",
     "___________________________________________________________________\n",
     "Added: dirprop\n",
-    "   + r2value\n",
+    "## -0,0 +1 ##\n",
+    "+r2value\n",
     "\n",
-    "\n",
     "Property changes on: iota\n",
     "___________________________________________________________________\n",
     "Added: fileprop\n",
-    "   + r2value\n",
-    "\n" ]
+    "## -0,0 +1 ##\n",
+    "+r2value\n"]
+

   expected_output_r2_r1 = list(expected_output_r1_r2)
   expected_output_r2_r1[3] = expected_output_r2_r1[3].replace("Added",
                                                               "Deleted")
-  expected_output_r2_r1[4] = "   - r2value\n"
+  expected_output_r2_r1[4] = "## -1 +0,0 ##\n"
+  expected_output_r2_r1[5] = "-r2value\n"
   expected_output_r2_r1[9] = expected_output_r2_r1[9].replace("Added",
                                                               "Deleted")
-  expected_output_r2_r1[10] = "   - r2value\n"
+  expected_output_r2_r1[10] = "## -1 +0,0 ##\n"
+  expected_output_r2_r1[11] = "-r2value\n"


   os.chdir(sbox.wc_dir)
@@ -2072,20 +2076,22 @@
     "Property changes on: A\n",
     "___________________________________________________________________\n",
     "Modified: dirprop\n",
-    "   - r2value\n",
-    "   + workingvalue\n",
+    "## -1 +1 ##\n",
+    "-r2value\n",
+    "+workingvalue\n",
     "Added: newdirprop\n",
-    "   + newworkingvalue\n",
+    "## -0,0 +1 ##\n",
+    "+newworkingvalue\n",
     "\n",
-    "\n",
     "Property changes on: iota\n",
     "___________________________________________________________________\n",
     "Modified: fileprop\n",
-    "   - r2value\n",
-    "   + workingvalue\n",
+    "## -1 +1 ##\n",
+    "-r2value\n",
+    "+workingvalue\n",
     "Added: newfileprop\n",
-    "   + newworkingvalue\n",
-    "\n" ]
+    "## -0,0 +1 ##\n",
+    "+newworkingvalue\n" ]

   os.chdir(sbox.wc_dir)

@@ -2153,17 +2159,17 @@
     "Property changes on: foo\n",
     "___________________________________________________________________\n",
     "Added: propname\n",
-    "   + propvalue\n",
-    "\n",
+    "## -0,0 +1 ##\n",
+    "+propvalue\n",
     ]
   diff_X_r1_r3 = [
     "\n",
     "Property changes on: X\n",
     "___________________________________________________________________\n",
     "Added: propname\n",
-    "   + propvalue\n",
-    "\n",
-  ]
+    "## -0,0 +1 ##\n",
+    "+propvalue\n",
+    ]
   diff_bar_r1_r3 = make_diff_header("X/bar", "revision 0", "revision 3") + [
     "@@ -0,0 +1 @@\n",
     "+content\n",
@@ -2171,8 +2177,8 @@
     "Property changes on: " + os.path.join('X', 'bar') + "\n",
     "___________________________________________________________________\n",
     "Added: propname\n",
-    "   + propvalue\n",
-    "\n",
+    "## -0,0 +1 ##\n",
+    "+propvalue\n",
     ]

   expected_output_r1_r3 = diff_X_r1_r3 + diff_bar_r1_r3 + diff_foo_r1_r3
@@ -2588,31 +2594,32 @@
     "Property changes on: .\n",
     "___________________________________________________________________\n",
     "Added: foo1\n",
-    "   + bar1\n",
+    "## -0,0 +1 ##\n",
+    "+bar1\n",
     "\n",
-    "\n",
     "Property changes on: iota\n",
     "___________________________________________________________________\n",
     "Added: foo2\n",
-    "   + bar2\n",
+    "## -0,0 +1 ##\n",
+    "+bar2\n",
     "\n",
-    "\n",
     "Property changes on: A\n",
     "___________________________________________________________________\n",
     "Added: foo3\n",
-    "   + bar3\n",
+    "## -0,0 +1 ##\n",
+    "+bar3\n",
     "\n",
-    "\n",
     "Property changes on: " + os.path.join('A', 'B') + "\n",
     "___________________________________________________________________\n",
     "Added: foo4\n",
-    "   + bar4\n",
-    "\n" ]
+    "## -0,0 +1 ##\n",
+    "+bar4\n"]

   expected_empty = svntest.verify.UnorderedOutput(diff[:6])
   expected_files = svntest.verify.UnorderedOutput(diff[:12])
   expected_immediates = svntest.verify.UnorderedOutput(diff[:18])
-  expected_infinity = svntest.verify.UnorderedOutput(diff[:])
+  expected_infinity = svntest.verify.UnorderedOutput(diff[:6]
+                                                     + diff[12:] + diff[6:12])

   os.chdir(sbox.wc_dir)

@@ -2655,20 +2662,26 @@

   diff_wc_repos = [
     "\n",
-    "Property changes on: .\n",
+    "Property changes on: " + os.path.join('A', 'B') + "\n",
     "___________________________________________________________________\n",
-    "Modified: foo1\n",
-    "   - bar1\n",
-    "   + baz1\n",
+    "Modified: foo4\n",
+    "## -1 +1 ##\n",
+    "-bar4\n",
+    "+baz4\n",
     "\n",
-    "\n",
-    "Property changes on: iota\n",
+    "Property changes on: A\n",
     "___________________________________________________________________\n",
-    "Modified: foo2\n",
-    "   - bar2\n",
-    "   + baz2\n",
-    "\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",
+    "@@ -1 +1,2 @@\n",
+    " This is the file 'mu'.\n",
+    "+new text\n",
     "Index: iota\n",
     "===================================================================\n",
     "--- iota\t(revision 2)\n",
@@ -2676,30 +2689,25 @@
     "@@ -1 +1,2 @@\n",
     " This is the file 'iota'.\n",
     "+new text\n",
-    "Property changes on: A\n",
+    "\n",
+    "Property changes on: iota\n",
     "___________________________________________________________________\n",
-    "Modified: foo3\n",
-    "   - bar3\n",
-    "   + baz3\n",
+    "Modified: foo2\n",
+    "## -1 +1 ##\n",
+    "-bar2\n",
+    "+baz2\n",
     "\n",
-    "\n",
-    "Property changes on: " + os.path.join('A', 'B') + "\n",
+    "Property changes on: .\n",
     "___________________________________________________________________\n",
-    "Modified: foo4\n",
-    "   - bar4\n",
-    "   + baz4\n",
-    "\n",
-    "Index: A/mu\n",
-    "===================================================================\n",
-    "--- A/mu\t(revision 1)\n",
-    "+++ A/mu\t(working copy)\n",
-    "@@ -1 +1,2 @@\n",
-    " This is the file 'mu'.\n",
-    "+new text\n" ]
+    "Modified: foo1\n",
+    "## -1 +1 ##\n",
+    "-bar1\n",
+    "+baz1\n" ]

-  expected_empty = svntest.verify.UnorderedOutput(diff_wc_repos[:7])
-  expected_files = svntest.verify.UnorderedOutput(diff_wc_repos[1:22])
-  expected_immediates = svntest.verify.UnorderedOutput(diff_wc_repos[1:29])
+  expected_empty = svntest.verify.UnorderedOutput(diff_wc_repos[35:])
+  expected_files = svntest.verify.UnorderedOutput(diff_wc_repos[21:])
+  expected_immediates = svntest.verify.UnorderedOutput(diff_wc_repos[7:14]
+                                                       +diff_wc_repos[21:])
   expected_infinity = svntest.verify.UnorderedOutput(diff_wc_repos[:])

   svntest.actions.run_and_verify_svn(None, None, [],
Index: subversion/tests/cmdline/special_tests.py
==================================================================--- subversion/tests/cmdline/special_tests.py	(revision 38504)
+++ subversion/tests/cmdline/special_tests.py	(arbetskopia)
@@ -532,8 +532,8 @@
     "Property changes on: link\n",
     "___________________________________________________________________\n",
     "Added: svn:special\n",
-    "   + *\n",
-    "\n" ]
+    "## -0,0 +1 ##\n",
+    "+*\n" ]
   svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
                                      '.')
   # We should get the same output if we the diff the symlink itself.
Index: subversion/tests/cmdline/merge_tests.py
==================================================================--- subversion/tests/cmdline/merge_tests.py	(revision 38504)
+++ subversion/tests/cmdline/merge_tests.py	(arbetskopia)
@@ -1660,8 +1660,7 @@
     "Property changes on: " + branch_path + "\n",
     "___________________________________________________________________\n",
     "Added: " + SVN_PROP_MERGEINFO + "\n",
-    "   Merged /A/B/E:r2-3\n",
-    "\n", ]
+    "   Merged /A/B/E:r2-3\n" ]
   svntest.actions.run_and_verify_svn(None, expected_output, [], 'diff',
                                      branch_path)

Index: subversion/tests/cmdline/depth_tests.py
==================================================================--- subversion/tests/cmdline/depth_tests.py	(revision 38504)
+++ subversion/tests/cmdline/depth_tests.py	(arbetskopia)
@@ -1035,12 +1035,19 @@
                                      'commit', '-m', '', wc)

   diff = [
+    "Index: A/mu\n",
+    "===================================================================\n",
+    "--- A/mu\t(revision 2)\n",
+    "+++ A/mu\t(working copy)\n",
+    "@@ -1 +1 @@\n",
+    "-new text\n",
+    "+This is the file 'mu'.\n",
     "\n",
-    "Property changes on: .\n",
+    "Property changes on: A\n",
     "___________________________________________________________________\n",
-    "Deleted: foo\n",
-    "   - foo-val\n",
-    "\n",
+    "Deleted: bar\n",
+    "## -1 +0,0 ##\n",
+    "-bar-val\n",
     "Index: iota\n",
     "===================================================================\n",
     "--- iota\t(revision 2)\n",
@@ -1048,23 +1055,16 @@
     "@@ -1 +1 @@\n",
     "-new text\n",
     "+This is the file 'iota'.\n",
-    "Property changes on: A\n",
+    "\n",
+    "Property changes on: .\n",
     "___________________________________________________________________\n",
-    "Deleted: bar\n",
-    "   - bar-val\n",
-    "\n",
-    "\n",
-    "Index: A/mu\n",
-    "===================================================================\n",
-    "--- A/mu\t(revision 2)\n",
-    "+++ A/mu\t(working copy)\n",
-    "@@ -1 +1 @@\n",
-    "-new text\n",
-    "+This is the file 'mu'.\n" ]
+    "Deleted: foo\n",
+    "## -1 +0,0 ##\n",
+    "-foo-val\n"]

   os.chdir(wc_empty)

-  expected_output = svntest.verify.UnorderedOutput(diff[:6])
+  expected_output = svntest.verify.UnorderedOutput(diff[20:26])
   # The diff should contain only the propchange on '.'
   svntest.actions.run_and_verify_svn(None, expected_output, [],
                                      'diff', '-rHEAD')
@@ -1074,11 +1074,11 @@
                                      '--set-depth', 'files', '-r1')
   # The diff should contain only the propchange on '.' and the
   # contents change on iota.
-  expected_output = svntest.verify.UnorderedOutput(diff[:13])
+  expected_output = svntest.verify.UnorderedOutput(diff[13:26])
   svntest.actions.run_and_verify_svn(None, expected_output, [],
                                      'diff', '-rHEAD')
   # Do a diff at --depth empty.
-  expected_output = svntest.verify.UnorderedOutput(diff[:6])
+  expected_output = svntest.verify.UnorderedOutput(diff[20:26])
   svntest.actions.run_and_verify_svn(None, expected_output, [],
                                      'diff', '--depth', 'empty', '-rHEAD')

@@ -1087,11 +1087,11 @@
                                      '--set-depth', 'immediates', '-r1')
   # The diff should contain the propchanges on '.' and 'A' and the
   # contents change on iota.
-  expected_output = svntest.verify.UnorderedOutput(diff[:19])
+  expected_output = svntest.verify.UnorderedOutput(diff[7:26])
   svntest.actions.run_and_verify_svn(None, expected_output, [],
                                     'diff', '-rHEAD')
   # Do a diff at --depth files.
-  expected_output = svntest.verify.UnorderedOutput(diff[:13])
+  expected_output = svntest.verify.UnorderedOutput(diff[13:26])
   svntest.actions.run_and_verify_svn(None, expected_output, [],
                                      'diff', '--depth', 'files', '-rHEAD')

@@ -1104,7 +1104,7 @@
   svntest.actions.run_and_verify_svn(None, expected_output, [],
                                      'diff', '-rHEAD')
   # Do a diff at --depth immediates.
-  expected_output = svntest.verify.UnorderedOutput(diff[:19])
+  expected_output = svntest.verify.UnorderedOutput(diff[7:])
   svntest.actions.run_and_verify_svn(None, expected_output, [],
                                     'diff', '--depth', 'immediates', '-rHEAD')

Index: subversion/include/svn_diff.h
==================================================================--- subversion/include/svn_diff.h	(revision 38504)
+++ subversion/include/svn_diff.h	(arbetskopia)
@@ -667,15 +667,37 @@
                           const svn_diff_file_options_t *options,
                           apr_pool_t *pool);

-
 /** Outputs the @a diff object generated by svn_diff_mem_string_diff()
  * in unified diff format on @a output_stream, using @a original
  * and @a modified for the text in the output.
- * Outputs the header and markers in @a header_encoding.
+ * A diff header is only written to the output if @a with_diff_header
+ * is TRUE.
  *
+ * Outputs the header and hunk delimiters in @a header_encoding.
+ * A @a hunk_delimiter can optionally be specified.
+ * If @a hunk_delimiter is NULL, use the default hunk delimiter "@@".
+ *
  * @a original_header and @a modified header are
  * used to fill the field after the "---" and "+++" header markers.
  *
+ * @since New in 1.7.
+ */
+svn_error_t *
+svn_diff_mem_string_output_unified2(svn_stream_t *output_stream,
+                                    svn_diff_t *diff,
+                                    svn_boolean_t with_diff_header,
+                                    const char *hunk_delimiter,
+                                    const char *original_header,
+                                    const char *modified_header,
+                                    const char *header_encoding,
+                                    const svn_string_t *original,
+                                    const svn_string_t *modified,
+                                    apr_pool_t *pool);
+
+/** Similar to svn_diff_mem_string_output_unified2() but with
+ * @a with_diff_header always set to TRUE and @a hunk_delimiter always
+ * set to NULL.
+ *
  * @since New in 1.5.
  */
 svn_error_t *
Index: subversion/libsvn_client/diff.c
==================================================================--- subversion/libsvn_client/diff.c	(revision 38504)
+++ subversion/libsvn_client/diff.c	(arbetskopia)
@@ -49,6 +49,7 @@
 #include "svn_time.h"
 #include "svn_sorts.h"
 #include "svn_base64.h"
+#include "svn_subst.h"
 #include "client.h"

 #include "private/svn_wc_private.h"
@@ -167,6 +168,35 @@
                           _("Path '%s' must be an immediate child of " \
                             "the directory '%s'"), path, relative_to_dir)

+/* A helper function used by display_prop_diffs.
+   TOKEN is a string holding a property value.
+   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. */
+static const svn_string_t *
+maybe_append_eol(const svn_string_t *token, apr_pool_t *pool)
+{
+  const char *curp;
+
+  if (token->len == 0)
+    return token;
+
+  curp = token->data + token->len - 1;
+  if (*curp == '\r')
+    {
+      return token;
+    }
+  else if (*curp != '\n')
+    {
+      return svn_string_createf(pool, "%s%s", token->data, APR_EOL_STR);
+    }
+  else
+    {
+      return token;
+    }
+}
+
 /* A helper func that writes out verbal descriptions of property diffs
    to FILE.   Of course, the apr_file_t will probably be the 'outfile'
    passed to svn_client_diff5, which is probably stdout. */
@@ -242,53 +272,43 @@
           continue;
         }

-      /* For now, we have a rather simple heuristic: if this is an
-         "svn:" property, then assume the value is UTF-8 and must
-         therefore be converted before printing.  Otherwise, just
-         print whatever's there and hope for the best. */
       {
-        svn_boolean_t val_is_utf8 = svn_prop_is_svn_prop(propchange->name);
+        svn_stream_t *os = svn_stream_from_aprfile2(file, TRUE, pool);
+        svn_diff_t *diff;
+        svn_diff_file_options_t options;
+        const svn_string_t *tmp;
+        const svn_string_t *orig;
+        const svn_string_t *val;

-        if (original_value != NULL)
-          {
-            if (val_is_utf8)
-              {
-                SVN_ERR(file_printf_from_utf8
-                        (file, encoding,
-                         "   - %s" APR_EOL_STR, original_value->data));
-              }
-            else
-              {
-                /* ### todo: check for error? */
-                apr_file_printf
-                  (file, "   - %s" APR_EOL_STR, original_value->data);
-              }
-          }
+        /* 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. */
+        tmp = original_value ? original_value : svn_string_create("", pool);
+        orig = maybe_append_eol(tmp, pool);

-        if (propchange->value != NULL)
-          {
-            if (val_is_utf8)
-              {
-                SVN_ERR(file_printf_from_utf8
-                        (file, encoding, "   + %s" APR_EOL_STR,
-                         propchange->value->data));
-              }
-            else
-              {
-                /* ### todo: check for error? */
-                apr_file_printf(file, "   + %s" APR_EOL_STR,
-                                propchange->value->data);
-              }
-          }
+        tmp = propchange->value ? propchange->value :
+                                  svn_string_create("", pool);
+        val = maybe_append_eol(tmp, pool);
+
+        SVN_ERR(svn_diff_mem_string_diff(&diff, orig, val, &options, pool));
+
+        /* UNIX patch will try to apply a diff even if the diff header
+         * is missing. It tries to be helpful by asking the user for a
+         * target filename when it can't determine the target filename
+         * from the diff header. But there usually are no files which
+         * UNIX patch could apply the property diff to, so we use "##"
+         * instead of "@@" as the default hunk delimiter for property diffs.
+         * We also supress the diff header. */
+        SVN_ERR(svn_diff_mem_string_output_unified2(os, diff, FALSE, "##",
+                                           svn_dirent_local_style(path, pool),
+                                           svn_dirent_local_style(path, pool),
+                                           encoding, orig, val, pool));
+        SVN_ERR(svn_stream_close(os));
+
       }
     }

-  /* ### todo [issue #1533]: Use file_printf_from_utf8() to convert this
-     to native encoding, at least conditionally?  Or is it better to
-     have under_string always output the same eol, so programs can
-     find it consistently?  Also, what about checking for error? */
-  apr_file_printf(file, APR_EOL_STR);
-
   return SVN_NO_ERROR;
 }


