Hi Philip, On 7/17/2017 4:14 AM, Philip Martin wrote: > - move the conversion from export_directory to svn_client_export5 > - change the parameter names in export_file_ev2, export_file, > export_directory > - remove the path code from those functions as it is never used > - add SVN_ERR_ASSERT(svn_path_is_url(from_url))
Thanks for your feedback! That change makes perfect sense. Here is a second attempt at this patch that I think addresses everything you listed. Patch with log message is attached. Doug
Add ability to specify revision when exporting from a working copy. Although svn_client_export5's documentation previously specified that the revision was only relevant when exporting from a repository URL, it is still a useful feature to be able to specify a revision when exporting from a working copy. This patch ensures that svn_client_export5 only deals with the repository URL in cases where a revision is supplied. This resolves an assertion failure if a working copy path is supplied and there are relative externals. * subversion/include/svn_client.h (svn_client_export5): Update documentation to indicate that revision is no longer only used when exporting from a repository URL. * subversion/libsvn_client/export.c (export_file_ev2, export_file, export_directory): Change to only handle URLs and assert that the supplied from_url parameter is actually a URL. (svn_client_export5): If exporting a working copy requires a URL, convert the working copy path to a URL prior to passing it to the export_* functions mentioned above. * subversion/tests/cmdline/export_tests.py (export_revision_with_root_relative_external): Remove XFail tag, and update the test to check for correct output and export results Index: subversion/include/svn_client.h =================================================================== --- subversion/include/svn_client.h (revision 1802187) +++ subversion/include/svn_client.h (working copy) @@ -6251,8 +6251,7 @@ svn_client_revprop_list(apr_hash_t **props, * #svn_opt_revision_unspecified, then it defaults to #svn_opt_revision_head * for URLs or #svn_opt_revision_working for WC targets. * - * @a revision is the revision that should be exported, which is only used - * when exporting from a repository. + * @a revision is the revision that should be exported. * * @a peg_revision and @a revision must not be @c NULL. * Index: subversion/libsvn_client/export.c =================================================================== --- subversion/libsvn_client/export.c (revision 1802187) +++ subversion/libsvn_client/export.c (working copy) @@ -1148,7 +1148,7 @@ get_editor_ev2(const svn_delta_editor_t **export_e } static svn_error_t * -export_file_ev2(const char *from_path_or_url, +export_file_ev2(const char *from_url, const char *to_path, struct edit_baton *eb, svn_client__pathrev_t *loc, @@ -1156,23 +1156,21 @@ static svn_error_t * svn_boolean_t overwrite, apr_pool_t *scratch_pool) { - svn_boolean_t from_is_url = svn_path_is_url(from_path_or_url); apr_hash_t *props; svn_stream_t *tmp_stream; svn_node_kind_t to_kind; + SVN_ERR_ASSERT(svn_path_is_url(from_url)); + if (svn_path_is_empty(to_path)) { - if (from_is_url) - to_path = svn_uri_basename(from_path_or_url, scratch_pool); - else - to_path = svn_dirent_basename(from_path_or_url, NULL); + to_path = svn_uri_basename(from_url, scratch_pool); eb->root_path = to_path; } else { - SVN_ERR(append_basename_if_dir(&to_path, from_path_or_url, - from_is_url, scratch_pool)); + SVN_ERR(append_basename_if_dir(&to_path, from_url, + TRUE, scratch_pool)); eb->root_path = to_path; } @@ -1204,7 +1202,7 @@ static svn_error_t * } static svn_error_t * -export_file(const char *from_path_or_url, +export_file(const char *from_url, const char *to_path, struct edit_baton *eb, svn_client__pathrev_t *loc, @@ -1216,20 +1214,18 @@ static svn_error_t * apr_hash_index_t *hi; struct file_baton *fb = apr_pcalloc(scratch_pool, sizeof(*fb)); svn_node_kind_t to_kind; - svn_boolean_t from_is_url = svn_path_is_url(from_path_or_url); + SVN_ERR_ASSERT(svn_path_is_url(from_url)); + if (svn_path_is_empty(to_path)) { - if (from_is_url) - to_path = svn_uri_basename(from_path_or_url, scratch_pool); - else - to_path = svn_dirent_basename(from_path_or_url, NULL); + to_path = svn_uri_basename(from_url, scratch_pool); eb->root_path = to_path; } else { - SVN_ERR(append_basename_if_dir(&to_path, from_path_or_url, - from_is_url, scratch_pool)); + SVN_ERR(append_basename_if_dir(&to_path, from_url, + TRUE, scratch_pool)); eb->root_path = to_path; } @@ -1288,7 +1284,7 @@ static svn_error_t * } static svn_error_t * -export_directory(const char *from_path_or_url, +export_directory(const char *from_url, const char *to_path, struct edit_baton *eb, svn_client__pathrev_t *loc, @@ -1307,6 +1303,8 @@ static svn_error_t * void *report_baton; svn_node_kind_t kind; + SVN_ERR_ASSERT(svn_path_is_url(from_url)); + if (!ENABLE_EV2_IMPL) SVN_ERR(get_editor_ev1(&export_editor, &edit_baton, eb, ctx, scratch_pool, scratch_pool)); @@ -1355,7 +1353,7 @@ static svn_error_t * SVN_ERR(svn_dirent_get_absolute(&to_abspath, to_path, scratch_pool)); SVN_ERR(svn_client__export_externals(eb->externals, - from_path_or_url, + from_url, to_abspath, eb->repos_root_url, depth, native_eol, ignore_keywords, @@ -1402,8 +1400,12 @@ svn_client_export5(svn_revnum_t *result_rev, svn_client__pathrev_t *loc; svn_ra_session_t *ra_session; svn_node_kind_t kind; + const char *from_url; struct edit_baton *eb = apr_pcalloc(pool, sizeof(*eb)); + SVN_ERR(svn_client_url_from_path2(&from_url, from_path_or_url, + ctx, pool, pool)); + /* Get the RA connection. */ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc, from_path_or_url, NULL, @@ -1428,15 +1430,15 @@ svn_client_export5(svn_revnum_t *result_rev, if (kind == svn_node_file) { if (!ENABLE_EV2_IMPL) - SVN_ERR(export_file(from_path_or_url, to_path, eb, loc, ra_session, + SVN_ERR(export_file(from_url, to_path, eb, loc, ra_session, overwrite, pool)); else - SVN_ERR(export_file_ev2(from_path_or_url, to_path, eb, loc, + SVN_ERR(export_file_ev2(from_url, to_path, eb, loc, ra_session, overwrite, pool)); } else if (kind == svn_node_dir) { - SVN_ERR(export_directory(from_path_or_url, to_path, + SVN_ERR(export_directory(from_url, to_path, eb, loc, ra_session, overwrite, ignore_externals, ignore_keywords, depth, native_eol, ctx, pool)); Index: subversion/tests/cmdline/export_tests.py =================================================================== --- subversion/tests/cmdline/export_tests.py (revision 1802187) +++ subversion/tests/cmdline/export_tests.py (working copy) @@ -1070,7 +1070,6 @@ def export_file_externals2(sbox): expected_output, expected_disk) -@XFail() def export_revision_with_root_relative_external(sbox): "export a revision with root-relative external" sbox.build() @@ -1089,18 +1088,37 @@ def export_revision_with_root_relative_external(sb # Update the working copy to receive file external svntest.main.run_svn(None, 'up', wc_dir) + # Update the expected disk tree to include the external. + expected_disk = svntest.main.greek_state.copy() + expected_disk.add({ + 'A/C/exfile_alpha' : Item("This is the file 'alpha'.\n"), + }) + + # Update the expected output to include the external. + expected_output = svntest.main.greek_state.copy() + expected_output.add({ + 'A/C/exfile_alpha' : Item("This is the file 'alpha'.\r"), + }) + expected_output.desc[''] = Item() + expected_output.tweak(contents=None, status='A ') + # Export revision 2 from URL export_target = sbox.add_wc_path('export_url') - svntest.actions.run_and_verify_svn(None, [], - 'export', sbox.repo_url, export_target, - '-r', 2) + expected_output.wc_dir = export_target + svntest.actions.run_and_verify_export(sbox.repo_url, + export_target, + expected_output, + expected_disk, + '-r', 2) # Export revision 2 from WC - # Fails (canonicalize: Assertion `*src != '/'' failed) export_target = sbox.add_wc_path('export_wc') - svntest.actions.run_and_verify_svn(None, [], - 'export', sbox.wc_dir, export_target, - '-r', 2) + expected_output.wc_dir = export_target + svntest.actions.run_and_verify_export(sbox.wc_dir, + export_target, + expected_output, + expected_disk, + '-r', 2) ########################################################################