Hi, This patch enhances the current "svn diff" by adding a new "--diff-copy-from" switch. I have attached the patch and the log message along with this mail. Please review and share your comments on the same.
I am resending this patch with the extension added to the log and the patch files. Regards Prabhu
[[[ Make svn diff to accept "--diff-copy-from" inorder to compare/diff against the copy-source file. * subversion/libsvn_ra/deprecated.c (): deprecated svn_ra_do_diff3 (svn_ra_do_diff2): pass FALSE for 'diff_copy_from' argument in do_diff function. * subversion/libsvn_ra/wrapper_template.h (compat_do_diff): pass FALSE for 'diff_copy_from' argument in do_diff function. * subversion/libsvn_ra/ra_loader.c (svn_ra_do_diff4): introduced 'diff_copy_from' argument. pass 'diff_copy_from' argument in do_diff function. * subversion/libsvn_ra/ra_loader.h svn_ra__vtable_t: introduced 'diff-copy-from' argument in do_diff. * subversion/libsvn_ra_local/ra_plugin.c (svn_ra_local__do_diff): introduced 'diff_copy_from' argument. if 'diff_copy_from', pass true for send_copyfrom_args if 'diff_copy_from', pass false for ignore_ancestry * subversion/libsvn_ra_svn/client.c (ra_svn_diff): introduced 'diff_copy_from' option and pass it to svn_ra_svn_write_cmd function. * subversion/svn/cl.h svn_cl__opt_state_t: introduced 'diff_copy_from' option. * subversion/svn/diff-cmd.c (svn_cl__diff): passed 'diff_copy_from' option to svn_client_diff5 function and the svn_client_diff_peg5 function. * subversion/svn/log-cmd.c (log_entry_receiver): passed false for diff_copy_from to svn_client_diff5 function. * subversion/svn/main.c (): introduced the diff_copy_from option and display information to user. svn_cl__options[]: added information about the diff_copy_from option. svn_cl__cmd_table[]: added diff-copy-from to the subcommand table. (main): handle the 'diff-copy-from' case. * subversion/include/svn_client.h (svn_client_diff5): introduced the 'diff_copy_from' argument. (svn_client_diff_peg5): introduced the 'diff_copy_from' argument. * subversion/include/svn_ra.h (): deprecated svn_ra_do_diff3 and introduced the svn_ra_do_diff4 to accept 'diff_copy_from' argument. * subversion/libsvn_client/deprecated.c (svn_client_diff4): pass false for diff_copy_from in svn_client_diff5 for backporting purpose. (svn_client_diff_peg4):pass false for diff_copy_from in svn_client_diff_peg5 for backporting purpose. * subversion/libsvn_client/repos_diff.c edit_baton: store the value of diff_copy_from. (get_file_from_ra): introduced the 'path' argument to pass the copyfrom_path. (diff_deleted_dir): passed path in the 'path' argument. (delete_entry): pass 'path' in the get_file_from_ra function. (add_file): if 'diff_copy_from' and copyfrom_revision are valid, add the file from the copy-source. (close_file): if diff_copy_from is set, call the file_changed callback. (svn_client__get_diff_editor): introduced the 'diff_copy_from' argument and assigned it in the edit baton. * subversion/libsvn_client/client.h (svn_client__get_diff_editor): introduced the 'diff_copy_from' argument. * subversion/libsvn_client/merge.c (drive_merge_report_editor): pass false for diff_copy_from to svn_ra_do_diff4 function and svn_client__get_diff_editor funtion. * subversion/libsvn_client/diff.c (diff_repos_repos): if diff_copy_from is set, perform diff with respect to the copy-source. (diff_repos_wc): if diff_copy_from is set, perform diff with respect to the copy-source. (do_diff): perform diff with respect to the diff_copy_from argument. (diff_summarize_repos_repos): pass false for 'diff_copy_from' to svn_ra_do_diff4 function. (svn_client_diff5): introduced the 'diff_copy_from' argument and pass it to do_diff function. (svn_client_diff_peg5): introduced the 'diff_copy_from' argument and pass it to do_diff function. * subversion/libsvn_ra_neon/ra_neon.h (svn_ra_neon__do_diff): introduced the 'diff_copy_from' argument. * subversion/libsvn_ra_neon/fetch.c (svn_ra_neon__do_diff): introduced the 'diff_copy_from' argument and pass it to make_reporter. * subversion/libsvn_ra_serf/ra_serf.h (svn_ra_serf__do_diff): introduced the 'diff_copy_from' argument. * subversion/libsvn_ra_serf/update.c (svn_ra_serf__do_diff): introduced the 'diff_copy_from' argument and pass it to make_update_reporter. * subversion/svnserve/serve.c (diff): introduced the 'diff_copy_from' argument and pass it to accept_reporter. Patch by: Prabhu Gnana Sundar <prabh...@collab.net> Suggested by: Kamesh Jayachandran <kam...@collab.net> ]]]
Index: subversion/libsvn_ra/deprecated.c =================================================================== --- subversion/libsvn_ra/deprecated.c (revision 1038978) +++ subversion/libsvn_ra/deprecated.c (working copy) @@ -248,6 +248,31 @@ keep_locks, pool); } +svn_error_t *svn_ra_do_diff3(svn_ra_session_t *session, + const svn_ra_reporter3_t **reporter, + void **report_baton, + svn_revnum_t revision, + const char *diff_target, + svn_depth_t depth, + svn_boolean_t ignore_ancestry, + svn_boolean_t text_deltas, + const char *versus_url, + const svn_delta_editor_t *diff_editor, + void *diff_baton, + apr_pool_t *pool) +{ + SVN_ERR_ASSERT(svn_path_is_empty(diff_target) + || svn_path_is_single_path_component(diff_target)); + return session->vtable->do_diff(session, + reporter, report_baton, + revision, diff_target, + depth, ignore_ancestry, + text_deltas, FALSE /* diff copy from */, + versus_url, diff_editor, + diff_baton, pool); +} + + svn_error_t *svn_ra_do_diff2(svn_ra_session_t *session, const svn_ra_reporter2_t **reporter, void **report_baton, @@ -270,8 +295,8 @@ &(b->reporter3), &(b->reporter3_baton), revision, diff_target, SVN_DEPTH_INFINITY_OR_FILES(recurse), - ignore_ancestry, text_deltas, versus_url, - diff_editor, diff_baton, pool); + ignore_ancestry, text_deltas, FALSE, + versus_url, diff_editor, diff_baton, pool); } svn_error_t *svn_ra_do_diff(svn_ra_session_t *session, Index: subversion/libsvn_ra/wrapper_template.h =================================================================== --- subversion/libsvn_ra/wrapper_template.h (revision 1038978) +++ subversion/libsvn_ra/wrapper_template.h (working copy) @@ -361,7 +361,7 @@ svn_depth_t depth = SVN_DEPTH_INFINITY_OR_FILES(recurse); SVN_ERR(VTBL.do_diff(session_baton, &reporter3, &baton3, revision, - diff_target, depth, ignore_ancestry, TRUE, + diff_target, depth, ignore_ancestry, TRUE, FALSE, versus_url, diff_editor, diff_baton, pool)); compat_wrap_reporter(reporter, report_baton, reporter3, baton3, pool); Index: subversion/libsvn_ra/ra_loader.c =================================================================== --- subversion/libsvn_ra/ra_loader.c (revision 1038978) +++ subversion/libsvn_ra/ra_loader.c (working copy) @@ -845,7 +845,7 @@ status_editor, status_baton, pool); } -svn_error_t *svn_ra_do_diff3(svn_ra_session_t *session, +svn_error_t *svn_ra_do_diff4(svn_ra_session_t *session, const svn_ra_reporter3_t **reporter, void **report_baton, svn_revnum_t revision, @@ -853,6 +853,7 @@ svn_depth_t depth, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, + svn_boolean_t diff_copy_from, const char *versus_url, const svn_delta_editor_t *diff_editor, void *diff_baton, @@ -864,7 +865,8 @@ reporter, report_baton, revision, diff_target, depth, ignore_ancestry, - text_deltas, versus_url, diff_editor, + text_deltas, diff_copy_from, + versus_url, diff_editor, diff_baton, pool); } Index: subversion/libsvn_ra/ra_loader.h =================================================================== --- subversion/libsvn_ra/ra_loader.h (revision 1038978) +++ subversion/libsvn_ra/ra_loader.h (working copy) @@ -159,10 +159,12 @@ svn_depth_t depth, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, + svn_boolean_t diff_copy_from, const char *versus_url, const svn_delta_editor_t *diff_editor, void *diff_baton, apr_pool_t *pool); + svn_error_t *(*get_log)(svn_ra_session_t *session, const apr_array_header_t *paths, svn_revnum_t start, Index: subversion/libsvn_ra_local/ra_plugin.c =================================================================== --- subversion/libsvn_ra_local/ra_plugin.c (revision 1038978) +++ subversion/libsvn_ra_local/ra_plugin.c (working copy) @@ -819,6 +819,7 @@ svn_depth_t depth, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, + svn_boolean_t diff_copy_from, const char *switch_url, const svn_delta_editor_t *update_editor, void *update_baton, @@ -832,7 +833,7 @@ switch_url, text_deltas, depth, - FALSE, + diff_copy_from ? TRUE : FALSE, ignore_ancestry, update_editor, update_baton, Index: subversion/libsvn_ra_svn/client.c =================================================================== --- subversion/libsvn_ra_svn/client.c (revision 1038978) +++ subversion/libsvn_ra_svn/client.c (working copy) @@ -1316,6 +1316,7 @@ svn_depth_t depth, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, + svn_boolean_t diff_copy_from, const char *versus_url, const svn_delta_editor_t *diff_editor, void *diff_baton, apr_pool_t *pool) @@ -1325,10 +1326,10 @@ svn_boolean_t recurse = DEPTH_TO_RECURSE(depth); /* Tell the server we want to start a diff. */ - SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "diff", "(?r)cbbcbw", rev, + SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "diff", "(?r)cbbcbwb", rev, target, recurse, ignore_ancestry, versus_url, text_deltas, - svn_depth_to_word(depth))); + svn_depth_to_word(depth), diff_copy_from)); SVN_ERR(handle_auth_request(sess_baton, pool)); /* Fetch a reporter for the caller to drive. The reporter will drive Index: subversion/svn/cl.h =================================================================== --- subversion/svn/cl.h (revision 1038978) +++ subversion/svn/cl.h (working copy) @@ -184,6 +184,7 @@ svn_boolean_t no_ignore; /* disregard default ignores & svn:ignore's */ svn_boolean_t no_auth_cache; /* do not cache authentication information */ svn_boolean_t no_diff_deleted; /* do not show diffs for deleted files */ + svn_boolean_t diff_copy_from; /* diff from the source */ svn_boolean_t show_copies_as_adds; /* do not diff copies with their source */ svn_boolean_t notice_ancestry; /* notice ancestry for diff-y operations */ svn_boolean_t ignore_ancestry; /* ignore ancestry for merge-y operations */ Index: subversion/svn/diff-cmd.c =================================================================== --- subversion/svn/diff-cmd.c (revision 1038978) +++ subversion/svn/diff-cmd.c (working copy) @@ -347,6 +347,7 @@ opt_state->depth, ! opt_state->notice_ancestry, opt_state->no_diff_deleted, + opt_state->diff_copy_from, opt_state->show_copies_as_adds, opt_state->force, opt_state->use_git_diff_format, @@ -392,6 +393,7 @@ opt_state->depth, ! opt_state->notice_ancestry, opt_state->no_diff_deleted, + opt_state->diff_copy_from, opt_state->show_copies_as_adds, opt_state->force, opt_state->use_git_diff_format, Index: subversion/svn/log-cmd.c =================================================================== --- subversion/svn/log-cmd.c (revision 1038978) +++ subversion/svn/log-cmd.c (working copy) @@ -303,6 +303,7 @@ svn_depth_infinity, FALSE, /* ignore ancestry */ TRUE, /* no diff deleted */ + FALSE, /* diff copy from */ FALSE, /* show copies as adds */ FALSE, /* ignore content type */ FALSE, /* use git diff format */ @@ -336,6 +337,7 @@ svn_depth_infinity, FALSE, /* ignore ancestry */ TRUE, /* no diff deleted */ + FALSE, /* diff copy from */ FALSE, /* show copies as adds */ FALSE, /* ignore content type */ FALSE, /* use git diff format */ Index: subversion/svn/main.c =================================================================== --- subversion/svn/main.c (revision 1038978) +++ subversion/svn/main.c (working copy) @@ -88,6 +88,7 @@ opt_no_auth_cache, opt_no_autoprops, opt_no_diff_deleted, + opt_diff_copy_from, opt_no_ignore, opt_no_unlock, opt_non_interactive, @@ -232,6 +233,8 @@ N_("try operation but make no changes")}, {"no-diff-deleted", opt_no_diff_deleted, 0, N_("do not print differences for deleted files")}, + {"diff-copy-from", opt_diff_copy_from, 0, + N_("print copy history of files")}, {"notice-ancestry", opt_notice_ancestry, 0, N_("notice ancestry when calculating differences")}, {"ignore-ancestry", opt_ignore_ancestry, 0, @@ -352,6 +355,7 @@ {"nac", opt_no_auth_cache, 0, NULL}, {"dry", opt_dry_run, 0, NULL}, {"ndd", opt_no_diff_deleted, 0, NULL}, + {"dcf", opt_diff_copy_from, 0, NULL}, {"na", opt_notice_ancestry, 0, NULL}, {"ia", opt_ignore_ancestry, 0, NULL}, {"ie", opt_ignore_externals, 0, NULL}, @@ -543,8 +547,9 @@ "\n" " Use just 'svn diff' to display local modifications in a working copy.\n"), {'r', 'c', opt_old_cmd, opt_new_cmd, 'N', opt_depth, opt_diff_cmd, - opt_internal_diff, 'x', opt_no_diff_deleted, opt_show_copies_as_adds, - opt_notice_ancestry, opt_summarize, opt_changelist, opt_force, opt_xml, + opt_internal_diff, 'x', opt_no_diff_deleted, opt_diff_copy_from, + opt_show_copies_as_adds, opt_notice_ancestry, opt_summarize, + opt_changelist, opt_force, opt_xml, opt_use_git_diff_format} }, { "export", svn_cl__export, {0}, N_ ("Create an unversioned copy of a tree.\n" @@ -1624,6 +1629,9 @@ case opt_no_diff_deleted: opt_state.no_diff_deleted = TRUE; break; + case opt_diff_copy_from: + opt_state.diff_copy_from = TRUE; + break; case opt_show_copies_as_adds: opt_state.show_copies_as_adds = TRUE; break; Index: subversion/include/svn_client.h =================================================================== --- subversion/include/svn_client.h (revision 1038978) +++ subversion/include/svn_client.h (working copy) @@ -2633,6 +2633,9 @@ * * If @a no_diff_deleted is TRUE, then no diff output will be * generated on deleted files. + * + * If @a diff_copy_from is TRUE, then the diff output will be generated + * with respect to the copy-source. * * If @a show_copies_as_adds is TRUE, then copied files will not be diffed * against their copyfrom source, and will appear in the diff output @@ -2684,6 +2687,7 @@ svn_depth_t depth, svn_boolean_t ignore_ancestry, svn_boolean_t no_diff_deleted, + svn_boolean_t diff_copy_from, svn_boolean_t show_copies_as_adds, svn_boolean_t ignore_content_type, svn_boolean_t use_git_diff_format, @@ -2797,6 +2801,9 @@ * changed between @a start_revision and @a end_revision. @a path can * be either a working-copy path or URL. * + * If @a diff_copy_from is TRUE, then the diff output will be generated + * with respect to the copy-source. + * * If @a peg_revision is #svn_opt_revision_unspecified, behave * identically to svn_client_diff5(), using @a path for both of that * function's @a path1 and @a path2 argments. @@ -2815,6 +2822,7 @@ svn_depth_t depth, svn_boolean_t ignore_ancestry, svn_boolean_t no_diff_deleted, + svn_boolean_t diff_copy_from, svn_boolean_t show_copies_as_adds, svn_boolean_t ignore_content_type, svn_boolean_t use_git_diff_format, Index: subversion/include/svn_ra.h =================================================================== --- subversion/include/svn_ra.h (revision 1038978) +++ subversion/include/svn_ra.h (working copy) @@ -1336,6 +1336,8 @@ * handler returned by apply_textdelta will be called once with a NULL * @c svn_txdelta_window_t pointer. * + * Pass TRUE to @a diff_copy_from to do the diff against the copy-source. + * * Use @a pool for memory allocation. * * @note The reporter provided by this function does NOT supply copy- @@ -1345,10 +1347,10 @@ * needed, and sending too much data back, a pre-1.5 'recurse' * directive may be sent to the server, based on @a depth. * - * @since New in 1.5. + * @since New in 1.7. */ svn_error_t * -svn_ra_do_diff3(svn_ra_session_t *session, +svn_ra_do_diff4(svn_ra_session_t *session, const svn_ra_reporter3_t **reporter, void **report_baton, svn_revnum_t revision, @@ -1356,12 +1358,35 @@ svn_depth_t depth, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, + svn_boolean_t diff_copy_from, const char *versus_url, const svn_delta_editor_t *diff_editor, void *diff_baton, apr_pool_t *pool); /** + * Similar to svn_ra_do_diff4(), but not taking the @a diff_copy_from + * option, hence passing FALSE. + * + * New code should use svn_ra_do_diff4(). + * + * @deprecated Provided for compatibility with the 1.5 API. + */ +SVN_DEPRECATED +svn_error_t * +svn_ra_do_diff3(svn_ra_session_t *session, + const svn_ra_reporter3_t **reporter, + void **report_baton, + svn_revnum_t revision, + const char *diff_target, + svn_depth_t depth, + svn_boolean_t ignore_ancestry, + svn_boolean_t text_deltas, + const char *versus_url, + const svn_delta_editor_t *diff_editor, + void *diff_baton, + apr_pool_t *pool); +/** * Similar to svn_ra_do_diff3(), but taking @c svn_ra_reporter2_t * instead of @c svn_ra_reporter3_t, and therefore only able to report * @c svn_depth_infinity for depths. Perform the diff according to Index: subversion/libsvn_client/deprecated.c =================================================================== --- subversion/libsvn_client/deprecated.c (revision 1038978) +++ subversion/libsvn_client/deprecated.c (working copy) @@ -785,7 +785,7 @@ { return svn_client_diff5(options, path1, revision1, path2, revision2, relative_to_dir, depth, - ignore_ancestry, no_diff_deleted, FALSE, + ignore_ancestry, no_diff_deleted, FALSE, FALSE, FALSE, ignore_content_type, header_encoding, outfile, errfile, changelists, ctx, pool); } @@ -883,6 +883,7 @@ no_diff_deleted, FALSE, FALSE, + FALSE, ignore_content_type, header_encoding, outfile, Index: subversion/libsvn_client/repos_diff.c =================================================================== --- subversion/libsvn_client/repos_diff.c (revision 1038978) +++ subversion/libsvn_client/repos_diff.c (working copy) @@ -93,6 +93,9 @@ FALSE otherwise. */ svn_boolean_t walk_deleted_repos_dirs; + /* TRUE if diff has to be made against the copy source. */ + svn_boolean_t diff_copy_from; + /* A callback used to see if the client wishes to cancel the running operation. */ svn_cancel_func_t cancel_func; @@ -198,6 +201,9 @@ /* A cache of any property changes (svn_prop_t) received for this file. */ apr_array_header_t *propchanges; + /* The copyfrom_revision */ + svn_revnum_t copyfrom_revision; + /* The pool passed in by add_file or open_file. Also, the pool this file_baton is allocated in. */ apr_pool_t *pool; @@ -308,7 +314,9 @@ * the file. */ static svn_error_t * -get_file_from_ra(struct file_baton *b, svn_revnum_t revision) +get_file_from_ra(struct file_baton *b, + const char *path, + svn_revnum_t revision) { svn_stream_t *fstream; @@ -317,7 +325,7 @@ b->pool)); SVN_ERR(svn_ra_get_file(b->edit_baton->ra_session, - b->path, + path, revision, fstream, NULL, &(b->pristine_props), @@ -508,7 +516,7 @@ /* Compare a file being deleted against an empty file */ b = make_file_baton(path, FALSE, eb, iterpool); - SVN_ERR(get_file_from_ra(b, revision)); + SVN_ERR(get_file_from_ra(b, path, revision)); SVN_ERR(get_empty_file(b->edit_baton, &(b->path_end_revision))); @@ -573,7 +581,7 @@ /* Compare a file being deleted against an empty file */ b = make_file_baton(path, FALSE, eb, pool); - SVN_ERR(get_file_from_ra(b, eb->revision)); + SVN_ERR(get_file_from_ra(b, path, eb->revision)); SVN_ERR(get_empty_file(b->edit_baton, &(b->path_end_revision))); get_file_mime_types(&mimetype1, &mimetype2, b); @@ -791,8 +799,6 @@ struct dir_baton *pb = parent_baton; struct file_baton *b; - /* ### TODO: support copyfrom? */ - b = make_file_baton(path, TRUE, pb->edit_baton, pool); *file_baton = b; @@ -804,8 +810,28 @@ return SVN_NO_ERROR; } - SVN_ERR(get_empty_file(b->edit_baton, &(b->path_start_revision))); - b->pristine_props = pb->edit_baton->empty_hash; + if(pb->edit_baton->diff_copy_from && SVN_IS_VALID_REVNUM(copyfrom_revision)) + { + const char *preserved_url; + const char *repos_root; + b->copyfrom_revision = copyfrom_revision; + SVN_ERR(svn_ra_get_session_url(pb->edit_baton->ra_session, + &preserved_url, + pool)); + SVN_ERR(svn_ra_get_repos_root2(pb->edit_baton->ra_session, + &repos_root, + pool)); + SVN_ERR(svn_ra_reparent(pb->edit_baton->ra_session, repos_root, + pool)); + SVN_ERR(get_file_from_ra(b, copyfrom_path+1, copyfrom_revision)); + SVN_ERR(svn_ra_reparent(pb->edit_baton->ra_session, + preserved_url, pool)); + } + else + { + SVN_ERR(get_empty_file(b->edit_baton, &(b->path_start_revision))); + b->pristine_props = pb->edit_baton->empty_hash; + } return SVN_NO_ERROR; } @@ -831,7 +857,7 @@ return SVN_NO_ERROR; } - SVN_ERR(get_file_from_ra(b, base_revision)); + SVN_ERR(get_file_from_ra(b, path, base_revision)); return SVN_NO_ERROR; } @@ -962,7 +988,7 @@ const char *mimetype1, *mimetype2; get_file_mime_types(&mimetype1, &mimetype2, b); - if (b->added) + if (b->added && !eb->diff_copy_from) SVN_ERR(eb->diff_callbacks->file_added (local_dir_abspath, &content_state, &prop_state, &b->tree_conflicted, b->wcpath, @@ -981,7 +1007,7 @@ &b->tree_conflicted, b->wcpath, b->path_end_revision ? b->path_start_revision : NULL, b->path_end_revision, - b->edit_baton->revision, + eb->diff_copy_from ? b->copyfrom_revision : b->edit_baton->revision, b->edit_baton->target_revision, mimetype1, mimetype2, b->propchanges, b->pristine_props, @@ -1297,6 +1323,7 @@ svn_revnum_t revision, svn_wc_notify_func2_t notify_func, void *notify_baton, + svn_boolean_t diff_copy_from, svn_cancel_func_t cancel_func, void *cancel_baton, const svn_delta_editor_t **editor, @@ -1323,6 +1350,7 @@ eb->notify_func = notify_func; eb->notify_baton = notify_baton; eb->walk_deleted_repos_dirs = TRUE; + eb->diff_copy_from = diff_copy_from; eb->cancel_func = cancel_func; eb->cancel_baton = cancel_baton; Index: subversion/libsvn_client/client.h =================================================================== --- subversion/libsvn_client/client.h (revision 1038978) +++ subversion/libsvn_client/client.h (working copy) @@ -644,6 +644,7 @@ svn_revnum_t revision, svn_wc_notify_func2_t notify_func, void *notify_baton, + svn_boolean_t diff_copy_from, svn_cancel_func_t cancel_func, void *cancel_baton, const svn_delta_editor_t **editor, Index: subversion/libsvn_client/merge.c =================================================================== --- subversion/libsvn_client/merge.c (revision 1038978) +++ subversion/libsvn_client/merge.c (working copy) @@ -5052,14 +5052,14 @@ merge_b->dry_run, merge_b->ra_session2, revision1, notification_receiver, notify_b, - merge_b->ctx->cancel_func, + FALSE, merge_b->ctx->cancel_func, merge_b->ctx->cancel_baton, &diff_editor, &diff_edit_baton, pool)); - SVN_ERR(svn_ra_do_diff3(merge_b->ra_session1, + SVN_ERR(svn_ra_do_diff4(merge_b->ra_session1, &reporter, &report_baton, revision2, "", depth, merge_b->ignore_ancestry, - TRUE, /* text_deltas */ + TRUE /* text_deltas */, FALSE /*diff_copy_from*/, url2, diff_editor, diff_edit_baton, pool)); /* Drive the reporter. */ Index: subversion/libsvn_client/diff.c =================================================================== --- subversion/libsvn_client/diff.c (revision 1038978) +++ subversion/libsvn_client/diff.c (working copy) @@ -1681,6 +1681,7 @@ const svn_opt_revision_t *peg_revision, svn_depth_t depth, svn_boolean_t ignore_ancestry, + svn_boolean_t diff_copy_from, apr_pool_t *pool) { svn_ra_session_t *extra_ra_session; @@ -1733,13 +1734,13 @@ NULL, callbacks, callback_baton, depth, FALSE /* doesn't matter for diff */, extra_ra_session, rev1, NULL /* no notify_func */, NULL /* no notify_baton */, - ctx->cancel_func, ctx->cancel_baton, + diff_copy_from, ctx->cancel_func, ctx->cancel_baton, &diff_editor, &diff_edit_baton, pool)); /* We want to switch our txn into URL2 */ - SVN_ERR(svn_ra_do_diff3 + SVN_ERR(svn_ra_do_diff4 (ra_session, &reporter, &reporter_baton, rev2, target1, - depth, ignore_ancestry, TRUE, + depth, ignore_ancestry, TRUE, diff_copy_from, url2, diff_editor, diff_edit_baton, pool)); /* Drive the reporter; do the diff. */ @@ -1770,6 +1771,7 @@ svn_boolean_t reverse, svn_depth_t depth, svn_boolean_t ignore_ancestry, + svn_boolean_t diff_copy_from, svn_boolean_t show_copies_as_adds, svn_boolean_t use_git_diff_format, const apr_array_header_t *changelists, @@ -1878,13 +1880,14 @@ else callback_baton->revnum2 = rev; - SVN_ERR(svn_ra_do_diff3(ra_session, + SVN_ERR(svn_ra_do_diff4(ra_session, &reporter, &reporter_baton, rev, target ? svn_path_uri_decode(target, pool) : NULL, depth, ignore_ancestry, TRUE, /* text_deltas */ + diff_copy_from, url1, diff_editor, diff_edit_baton, pool)); @@ -1915,6 +1918,7 @@ const svn_opt_revision_t *peg_revision, svn_depth_t depth, svn_boolean_t ignore_ancestry, + svn_boolean_t diff_copy_from, svn_boolean_t show_copies_as_adds, svn_boolean_t use_git_diff_format, const apr_array_header_t *changelists, @@ -1934,15 +1938,16 @@ SVN_ERR(diff_repos_repos(callbacks, callback_baton, ctx, path1, path2, revision1, revision2, peg_revision, depth, ignore_ancestry, - pool)); + diff_copy_from, pool)); } else /* path2 is a working copy path */ { SVN_ERR(diff_repos_wc(path1, revision1, peg_revision, path2, revision2, FALSE, depth, - ignore_ancestry, show_copies_as_adds, - use_git_diff_format, changelists, - callbacks, callback_baton, ctx, pool)); + ignore_ancestry, diff_copy_from, + show_copies_as_adds, use_git_diff_format, + changelists, callbacks, callback_baton, + ctx, pool)); } } else /* path1 is a working copy path */ @@ -1951,9 +1956,10 @@ { SVN_ERR(diff_repos_wc(path2, revision2, peg_revision, path1, revision1, TRUE, depth, - ignore_ancestry, show_copies_as_adds, - use_git_diff_format, changelists, - callbacks, callback_baton, ctx, pool)); + ignore_ancestry, diff_copy_from, + show_copies_as_adds, use_git_diff_format, + changelists, callbacks, callback_baton, + ctx, pool)); } else /* path2 is a working copy path */ { @@ -2020,11 +2026,11 @@ ctx->cancel_baton, &diff_editor, &diff_edit_baton, pool)); /* We want to switch our txn into URL2 */ - SVN_ERR(svn_ra_do_diff3 + SVN_ERR(svn_ra_do_diff4 (ra_session, &reporter, &reporter_baton, rev2, target1, depth, ignore_ancestry, - FALSE /* do not create text delta */, url2, diff_editor, - diff_edit_baton, pool)); + FALSE /* do not create text delta */, FALSE /* diff_copy_from */, + url2, diff_editor, diff_edit_baton, pool)); /* Drive the reporter; do the diff. */ SVN_ERR(reporter->set_path(reporter_baton, "", rev1, @@ -2177,6 +2183,7 @@ svn_depth_t depth, svn_boolean_t ignore_ancestry, svn_boolean_t no_diff_deleted, + svn_boolean_t diff_copy_from, svn_boolean_t show_copies_as_adds, svn_boolean_t ignore_content_type, svn_boolean_t use_git_diff_format, @@ -2228,7 +2235,7 @@ return do_diff(&diff_callbacks, &diff_cmd_baton, ctx, path1, path2, revision1, revision2, &peg_revision, - depth, ignore_ancestry, show_copies_as_adds, + depth, ignore_ancestry, diff_copy_from, show_copies_as_adds, use_git_diff_format, changelists, pool); } @@ -2242,6 +2249,7 @@ svn_depth_t depth, svn_boolean_t ignore_ancestry, svn_boolean_t no_diff_deleted, + svn_boolean_t diff_copy_from, svn_boolean_t show_copies_as_adds, svn_boolean_t ignore_content_type, svn_boolean_t use_git_diff_format, @@ -2289,7 +2297,7 @@ return do_diff(&diff_callbacks, &diff_cmd_baton, ctx, path, path, start_revision, end_revision, peg_revision, - depth, ignore_ancestry, show_copies_as_adds, + depth, ignore_ancestry, diff_copy_from, show_copies_as_adds, use_git_diff_format, changelists, pool); } Index: subversion/libsvn_ra_serf/update.c =================================================================== --- subversion/libsvn_ra_serf/update.c (revision 1038978) +++ subversion/libsvn_ra_serf/update.c (working copy) @@ -2628,6 +2628,7 @@ svn_depth_t depth, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, + svn_boolean_t diff_copy_from, const char *versus_url, const svn_delta_editor_t *diff_editor, void *diff_baton, @@ -2638,7 +2639,8 @@ return make_update_reporter(ra_session, reporter, report_baton, revision, session->repos_url.path, versus_url, diff_target, - depth, ignore_ancestry, text_deltas, FALSE, + depth, ignore_ancestry, text_deltas, + diff_copy_from ? TRUE : FALSE, diff_editor, diff_baton, pool); } Index: subversion/libsvn_ra_serf/ra_serf.h =================================================================== --- subversion/libsvn_ra_serf/ra_serf.h (revision 1038978) +++ subversion/libsvn_ra_serf/ra_serf.h (working copy) @@ -1245,6 +1245,7 @@ svn_depth_t depth, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, + svn_boolean_t diff_copy_from, const char *versus_url, const svn_delta_editor_t *diff_editor, void *diff_baton, Index: subversion/libsvn_ra_neon/ra_neon.h =================================================================== --- subversion/libsvn_ra_neon/ra_neon.h (revision 1038978) +++ subversion/libsvn_ra_neon/ra_neon.h (working copy) @@ -349,6 +349,7 @@ svn_depth_t depth, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, + svn_boolean_t diff_copy_from, const char *versus_url, const svn_delta_editor_t *wc_diff, void *wc_diff_baton, Index: subversion/libsvn_ra_neon/fetch.c =================================================================== --- subversion/libsvn_ra_neon/fetch.c (revision 1038978) +++ subversion/libsvn_ra_neon/fetch.c (working copy) @@ -2809,6 +2809,7 @@ svn_depth_t depth, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, + svn_boolean_t diff_copy_from, const char *versus_url, const svn_delta_editor_t *wc_diff, void *wc_diff_baton, @@ -2821,7 +2822,7 @@ diff_target, versus_url, depth, - FALSE, + diff_copy_from ? TRUE : FALSE, ignore_ancestry, FALSE, wc_diff, Index: subversion/svnserve/serve.c =================================================================== --- subversion/svnserve/serve.c (revision 1038978) +++ subversion/svnserve/serve.c (working copy) @@ -1774,6 +1774,8 @@ /* Default to unknown. Old clients won't send depth, but we'll handle that by converting recurse if necessary. */ svn_depth_t depth = svn_depth_unknown; + /* Default to false. Pre-1.7 clients won't send diff-copy-from. */ + svn_boolean_t diff_copy_from = FALSE; /* Parse the arguments. */ if (params->nelts == 5) @@ -1786,10 +1788,10 @@ } else { - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "(?r)cbbcb?w", + SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "(?r)cbbcb?w?b", &rev, &target, &recurse, &ignore_ancestry, &versus_url, - &text_deltas, &depth_word)); + &text_deltas, &depth_word, &diff_copy_from)); } target = svn_uri_canonicalize(target, pool); versus_url = svn_uri_canonicalize(versus_url, pool); @@ -1812,7 +1814,8 @@ svn_revnum_t from_rev; SVN_ERR(accept_report(NULL, &from_rev, conn, pool, b, rev, target, versus_path, - text_deltas, depth, FALSE, ignore_ancestry)); + text_deltas, depth, diff_copy_from, + ignore_ancestry)); SVN_ERR(log_command(b, conn, pool, "%s", svn_log__diff(full_path, from_rev, versus_path, rev, depth, ignore_ancestry,