On Mon, Nov 29, 2010 at 01:43:20PM +0530, Prabhu Gnana Sundar wrote: > 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
Hi Prabhu, very impressive patch! I haven't tested it. But I've read over it and added a couple of remarks below. > 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")}, Maybe say N_("diff copied files against their source") or N_("follow 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. Maybe say: * If @a diff_copy_from is TRUE, diff copied files against the copyfrom * source, instead of diffing against the history of the file's path. > * > * 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. > + * See above. > * 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 */ The above comment just repeats the variable name. This comment is not terribly important because the variable name has a clear meaning, but maybe say: /* 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)); Reparenting can fail due to authz restrictions. Please catch related errors (see subversion/svn/log-cmd.c for an example). Maybe even add a regression test that makes sure this feature can cope with copyfrom paths that aren't accessible due to authz restrictions. > + 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*/, style nit: need more spaces in comment, like this: /* 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)); style nit: needs wrap at 78 columns, like this: &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,