Index: subversion/libsvn_diff/diff_memory.c =================================================================== --- subversion/libsvn_diff/diff_memory.c (revision 38477) +++ subversion/libsvn_diff/diff_memory.c (arbetskopia) @@ -426,7 +426,8 @@ /* Flush the hunk currently built up in BATON into the baton's output_stream */ static svn_error_t * -output_unified_flush_hunk(output_baton_t *baton) +output_unified_flush_hunk2(output_baton_t *baton, + const char *hunk_delimiter) { apr_off_t target_token; apr_size_t hunk_len; @@ -453,23 +454,37 @@ /* 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), + ? ("%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 + + + /* 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, - /* 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])); + " +%" 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)); @@ -480,6 +495,16 @@ return SVN_NO_ERROR; } +/* Flush the hunk currently built up in BATON + into the baton's output_stream */ +static svn_error_t * +output_unified_flush_hunk(output_baton_t *baton) +{ + SVN_ERR(output_unified_flush_hunk2(baton, "@@")); + + return SVN_NO_ERROR; +} + /* Implements svn_diff_output_fns_t::output_diff_modified */ static svn_error_t * output_unified_diff_modified(void *baton, @@ -530,8 +555,9 @@ svn_error_t * -svn_diff_mem_string_output_unified(svn_stream_t *output_stream, +svn_diff_mem_string_output_unified2(svn_stream_t *output_stream, svn_diff_t *diff, + svn_boolean_t property_diff, const char *original_header, const char *modified_header, const char *header_encoding, @@ -563,15 +589,20 @@ 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 (!property_diff) { + 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)); + if (property_diff) + SVN_ERR(output_unified_flush_hunk2(&baton, "##")); + else + SVN_ERR(output_unified_flush_hunk(&baton)); svn_pool_destroy(baton.pool); } @@ -579,7 +610,30 @@ 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, + FALSE, + original_header, + modified_header, + header_encoding, + original, + modified, + pool)); + return SVN_NO_ERROR; +} + /* diff3 merge output */ Index: subversion/include/svn_diff.h =================================================================== --- subversion/include/svn_diff.h (revision 38477) +++ subversion/include/svn_diff.h (arbetskopia) @@ -667,6 +667,29 @@ 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. + * Only if @a display_header is TRUE it outputs the header. Useful for + * property diffs. + * Outputs the header and markers in @a header_encoding. + * + * + * @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 display_headers, + 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); /** Outputs the @a diff object generated by svn_diff_mem_string_diff() * in unified diff format on @a output_stream, using @a original Index: subversion/libsvn_client/diff.c =================================================================== --- subversion/libsvn_client/diff.c (revision 38477) +++ subversion/libsvn_client/diff.c (arbetskopia) @@ -167,6 +167,32 @@ _("Path '%s' must be an immediate child of " \ "the directory '%s'"), path, relative_to_dir) +/* A helper func used by display_prop_diffs. It appends the systems default + eol character if there is none in the string. */ +static const svn_string_t * +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') + { + const char *tmp = apr_psprintf(pool, "%s%s", token->data, APR_EOL_STR); + return svn_string_create(tmp, pool); + } + 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 +268,38 @@ 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); + /* Use libsvn_diff for output.*/ + 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; - 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); - } - } + /* When setting or editing a property no eol character is inserted. + Since the diff is not useful anyway for patching properties an + eol character is appended to remove those pescious ' \ No newline + at end of file' lines. */ + tmp = original_value ? original_value : svn_string_create("", 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); - } - } + const svn_string_t *orig = append_eol(tmp, pool); + + tmp = propchange->value ? propchange->value : + svn_string_create("", pool); + + const svn_string_t *val = append_eol(tmp, pool); + + SVN_ERR(svn_diff_mem_string_diff(&diff, orig, val, &options, pool)); + + /* The diff is printed with special property settings */ + SVN_ERR(svn_diff_mem_string_output_unified2(os, diff, TRUE, + 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; }