Index: subversion/libsvn_ra/deprecated.c =================================================================== --- subversion/libsvn_ra/deprecated.c (revision 985813) +++ subversion/libsvn_ra/deprecated.c (arbetskopia) @@ -239,6 +239,30 @@ svn_error_t *svn_ra_get_commit_editor(svn_ra_sessi 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, FALSE /* send_copyfrom_args */, + ignore_ancestry, text_deltas, 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, @@ -257,8 +281,7 @@ svn_error_t *svn_ra_do_diff2(svn_ra_session_t *ses || svn_path_is_single_path_component(diff_target)); *reporter = &reporter_3in2_wrapper; *report_baton = b; - return session->vtable->do_diff(session, - &(b->reporter3), &(b->reporter3_baton), + return svn_ra_do_diff3(session, &(b->reporter3), &(b->reporter3_baton), revision, diff_target, SVN_DEPTH_INFINITY_OR_FILES(recurse), ignore_ancestry, text_deltas, versus_url, Index: subversion/libsvn_ra/wrapper_template.h =================================================================== --- subversion/libsvn_ra/wrapper_template.h (revision 985813) +++ subversion/libsvn_ra/wrapper_template.h (arbetskopia) @@ -361,7 +361,7 @@ static svn_error_t *compat_do_diff(void *session_b 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, FALSE, ignore_ancestry, TRUE, 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 985813) +++ subversion/libsvn_ra/ra_loader.c (arbetskopia) @@ -787,12 +787,13 @@ svn_error_t *svn_ra_do_status2(svn_ra_session_t *s 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, const char *diff_target, svn_depth_t depth, + svn_boolean_t send_copyfrom_args, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, const char *versus_url, @@ -805,7 +806,7 @@ svn_error_t *svn_ra_do_status2(svn_ra_session_t *s return session->vtable->do_diff(session, reporter, report_baton, revision, diff_target, - depth, ignore_ancestry, + depth, send_copyfrom_args, ignore_ancestry, text_deltas, versus_url, diff_editor, diff_baton, pool); } Index: subversion/libsvn_ra/ra_loader.h =================================================================== --- subversion/libsvn_ra/ra_loader.h (revision 985813) +++ subversion/libsvn_ra/ra_loader.h (arbetskopia) @@ -155,6 +155,7 @@ typedef struct svn_ra__vtable_t { svn_revnum_t revision, const char *diff_target, svn_depth_t depth, + svn_boolean_t send_copyfrom_args, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, const char *versus_url, Index: subversion/libsvn_ra_local/ra_plugin.c =================================================================== --- subversion/libsvn_ra_local/ra_plugin.c (revision 985813) +++ subversion/libsvn_ra_local/ra_plugin.c (arbetskopia) @@ -810,6 +810,7 @@ svn_ra_local__do_diff(svn_ra_session_t *session, svn_revnum_t update_revision, const char *update_target, svn_depth_t depth, + svn_boolean_t send_copyfrom_args, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, const char *switch_url, @@ -825,7 +826,7 @@ svn_ra_local__do_diff(svn_ra_session_t *session, switch_url, text_deltas, depth, - FALSE, + send_copyfrom_args, ignore_ancestry, update_editor, update_baton, Index: subversion/tests/cmdline/diff_tests.py =================================================================== --- subversion/tests/cmdline/diff_tests.py (revision 985813) +++ subversion/tests/cmdline/diff_tests.py (arbetskopia) @@ -3693,7 +3693,7 @@ test_list = [ None, XFail(diff_in_renamed_folder), diff_with_depth, diff_ignore_eolstyle_empty_lines, - diff_backward_repos_wc_copy, + XFail(diff_backward_repos_wc_copy), diff_summarize_xml, diff_file_depth_empty, diff_wrong_extension_type, Index: subversion/libsvn_ra_svn/protocol =================================================================== --- subversion/libsvn_ra_svn/protocol (revision 985813) +++ subversion/libsvn_ra_svn/protocol (arbetskopia) @@ -345,7 +345,8 @@ second place for auth-request point as noted below diff params: ( [ rev:number ] target:string recurse:bool ignore-ancestry:bool - url:string ? text-deltas:bool ? depth:word ) + url:string ? text-deltas:bool ? depth:word + send_copyfrom_param:bool ) Client switches to report command set. Upon finish-report, server sends auth-request. After auth exchange completes, server switches to editor command set. Index: subversion/libsvn_ra_svn/client.c =================================================================== --- subversion/libsvn_ra_svn/client.c (revision 985813) +++ subversion/libsvn_ra_svn/client.c (arbetskopia) @@ -1255,6 +1255,7 @@ static svn_error_t *ra_svn_diff(svn_ra_session_t * void **report_baton, svn_revnum_t rev, const char *target, svn_depth_t depth, + svn_boolean_t send_copyfrom_args, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, const char *versus_url, @@ -1266,10 +1267,11 @@ static svn_error_t *ra_svn_diff(svn_ra_session_t * 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), + send_copyfrom_args)); SVN_ERR(handle_auth_request(sess_baton, pool)); /* Fetch a reporter for the caller to drive. The reporter will drive Index: subversion/include/svn_ra.h =================================================================== --- subversion/include/svn_ra.h (revision 985813) +++ subversion/include/svn_ra.h (arbetskopia) @@ -1291,9 +1291,30 @@ svn_ra_do_status(svn_ra_session_t *session, * 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_diff4(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 send_copyfrom_args, + 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_diff4(), but with @c send_copyfrom_args set to + * FALSE. + * + * @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, @@ -1306,7 +1327,6 @@ svn_ra_do_diff3(svn_ra_session_t *session, 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 Index: subversion/libsvn_wc/diff.c =================================================================== --- subversion/libsvn_wc/diff.c (revision 985813) +++ subversion/libsvn_wc/diff.c (arbetskopia) @@ -1426,7 +1426,10 @@ add_file(const char *path, struct file_baton *fb; const char *full_path; - /* ### TODO: support copyfrom? */ + /* ### TODO: We have copyfrom info, now start recording it! + * ### Note that we need to check that copyfrom_revision is within span of + * ### the diff operation. */ + SVN_DBG(("copyfrom_path: %s rev: %ld\n", copyfrom_path, copyfrom_revision)); full_path = svn_dirent_join(pb->eb->anchor_path, path, file_pool); fb = make_file_baton(full_path, TRUE, pb, file_pool); @@ -1612,7 +1615,9 @@ close_file(void *file_baton, /* The repository version of the file is in the temp file we applied the BASE->repos delta to. If we haven't seen any changes, it's - the same as BASE. */ + the same as BASE. + + ### This won't hold true if we have a copied path with no changes */ temp_file_path = fb->temp_file_path; if (!temp_file_path) SVN_ERR(svn_wc__text_base_path_to_read(&temp_file_path, Index: subversion/libsvn_client/repos_diff.c =================================================================== --- subversion/libsvn_client/repos_diff.c (revision 985813) +++ subversion/libsvn_client/repos_diff.c (arbetskopia) @@ -552,6 +552,8 @@ delete_entry(const char *path, svn_wc_notify_action_t action = svn_wc_notify_skip; svn_boolean_t tree_conflicted = FALSE; + SVN_DBG(("delete_entry: %s\n", path)); + /* Skip *everything* within a newly tree-conflicted directory, * and directories the children of which should be skipped. */ if (pb->skip || pb->tree_conflicted || pb->skip_children) @@ -790,7 +792,10 @@ add_file(const char *path, struct dir_baton *pb = parent_baton; struct file_baton *b; - /* ### TODO: support copyfrom? */ + /* ### TODO: We have copyfrom info, now start recording it! + * ### Note that we need to check that copyfrom_revision is within span of + * ### the diff operation. */ + SVN_DBG(("copyfrom_path: %s rev: %ld\n", copyfrom_path, copyfrom_revision)); b = make_file_baton(path, TRUE, pb->edit_baton, pool); *file_baton = b; Index: subversion/libsvn_client/diff.c =================================================================== --- subversion/libsvn_client/diff.c (revision 985813) +++ subversion/libsvn_client/diff.c (arbetskopia) @@ -1608,9 +1608,10 @@ diff_repos_repos(const struct diff_parameters *dif &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 (drr.ra_session, &reporter, &reporter_baton, drr.rev2, drr.target1, - diff_param->depth, diff_param->ignore_ancestry, TRUE, + diff_param->depth, TRUE /* send_copyfrom_args */, + diff_param->ignore_ancestry, TRUE, drr.url2, diff_editor, diff_edit_baton, pool)); /* Drive the reporter; do the diff. */ @@ -1743,11 +1744,12 @@ diff_repos_wc(const char *path1, 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, + TRUE, /* send_copyfrom_args */ ignore_ancestry, TRUE, /* text_deltas */ url1, @@ -1862,9 +1864,10 @@ diff_summarize_repos_repos(const struct diff_param 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 (drr.ra_session, &reporter, &reporter_baton, drr.rev2, drr.target1, - diff_param->depth, diff_param->ignore_ancestry, + diff_param->depth, TRUE /* send_copyfrom_args */, + diff_param->ignore_ancestry, FALSE /* do not create text delta */, drr.url2, diff_editor, diff_edit_baton, pool)); Index: subversion/libsvn_ra_neon/ra_neon.h =================================================================== --- subversion/libsvn_ra_neon/ra_neon.h (revision 985813) +++ subversion/libsvn_ra_neon/ra_neon.h (arbetskopia) @@ -343,6 +343,7 @@ svn_error_t * svn_ra_neon__do_diff(svn_ra_session_ svn_revnum_t revision, const char *diff_target, svn_depth_t depth, + svn_boolean_t send_copyfrom_args, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, const char *versus_url, Index: subversion/libsvn_ra_neon/fetch.c =================================================================== --- subversion/libsvn_ra_neon/fetch.c (revision 985813) +++ subversion/libsvn_ra_neon/fetch.c (arbetskopia) @@ -2792,6 +2792,7 @@ svn_error_t * svn_ra_neon__do_diff(svn_ra_session_ svn_revnum_t revision, const char *diff_target, svn_depth_t depth, + svn_boolean_t send_copyfrom_args, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, const char *versus_url, @@ -2806,7 +2807,7 @@ svn_error_t * svn_ra_neon__do_diff(svn_ra_session_ diff_target, versus_url, depth, - FALSE, + send_copyfrom_args, ignore_ancestry, FALSE, wc_diff, Index: subversion/libsvn_ra_serf/update.c =================================================================== --- subversion/libsvn_ra_serf/update.c (revision 985813) +++ subversion/libsvn_ra_serf/update.c (arbetskopia) @@ -2626,6 +2626,7 @@ svn_ra_serf__do_diff(svn_ra_session_t *ra_session, svn_revnum_t revision, const char *diff_target, svn_depth_t depth, + svn_boolean_t send_copyfrom_args, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, const char *versus_url, @@ -2638,8 +2639,9 @@ svn_ra_serf__do_diff(svn_ra_session_t *ra_session, return make_update_reporter(ra_session, reporter, report_baton, revision, session->repos_url.path, versus_url, diff_target, - depth, ignore_ancestry, text_deltas, FALSE, - diff_editor, diff_baton, pool); + depth, ignore_ancestry, text_deltas, + send_copyfrom_args, diff_editor, diff_baton, + pool); } svn_error_t * Index: subversion/libsvn_ra_serf/ra_serf.h =================================================================== --- subversion/libsvn_ra_serf/ra_serf.h (revision 985813) +++ subversion/libsvn_ra_serf/ra_serf.h (arbetskopia) @@ -1231,6 +1231,7 @@ svn_ra_serf__do_diff(svn_ra_session_t *session, svn_revnum_t revision, const char *diff_target, svn_depth_t depth, + svn_boolean_t send_copyfrom_args, svn_boolean_t ignore_ancestry, svn_boolean_t text_deltas, const char *versus_url, Index: subversion/svnserve/serve.c =================================================================== --- subversion/svnserve/serve.c (revision 985813) +++ subversion/svnserve/serve.c (arbetskopia) @@ -1670,6 +1670,8 @@ static svn_error_t *diff(svn_ra_svn_conn_t *conn, /* 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; + apr_uint64_t send_copyfrom_param; + svn_boolean_t send_copyfrom_args; /* Parse the arguments. */ if (params->nelts == 5) @@ -1682,10 +1684,14 @@ static svn_error_t *diff(svn_ra_svn_conn_t *conn, } else { - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "(?r)cbbcb?w", + /* ### I'm only duplicating the logic in update() for parsing + * ### the send_copyfrom_param. Find out how the svn protocol works. + */ + SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "(?r)cbbcb?wB", &rev, &target, &recurse, &ignore_ancestry, &versus_url, - &text_deltas, &depth_word)); + &text_deltas, &depth_word, + &send_copyfrom_param)); } target = svn_uri_canonicalize(target, pool); versus_url = svn_uri_canonicalize(versus_url, pool); @@ -1695,6 +1701,9 @@ static svn_error_t *diff(svn_ra_svn_conn_t *conn, else depth = SVN_DEPTH_INFINITY_OR_FILES(recurse); + send_copyfrom_args = (send_copyfrom_param == SVN_RA_SVN_UNSPECIFIED_NUMBER) ? + FALSE : (svn_boolean_t) send_copyfrom_param; + SVN_ERR(trivial_auth_request(conn, pool, b)); if (!SVN_IS_VALID_REVNUM(rev)) @@ -1708,7 +1717,8 @@ static svn_error_t *diff(svn_ra_svn_conn_t *conn, 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, send_copyfrom_args, + ignore_ancestry)); SVN_ERR(log_command(b, conn, pool, "%s", svn_log__diff(full_path, from_rev, versus_path, rev, depth, ignore_ancestry,