Author: stsp
Date: Sat Mar 8 11:42:48 2014
New Revision: 1575525
URL: http://svn.apache.org/r1575525
Log:
Fix and regression test for issue #4427, "export external files".
Exports from working copies were omitting file externals due
to a logic bug in the externals handling of svn_client_export5().
* subversion/libsvn_client/export.c
(export_info_baton): Add 'exporting_external' flag.
(export_node): Don't skip file externals if 'exporting_external' flag is set.
(do_export): Wrapper for logic of svn_client_export5(), with an additional
'exporting_external' parameter which is passed to exporting_node() via
the export_info_baton. Set the flag if recursing into do_export() to
export an external.
(svn_client_export5): Re-implement as wrapper of do_export().
* subversion/tests/cmdline/export_tests.py
(export_file_external, test_list): New regression test which passes
with the above change and fails without it.
Modified:
subversion/trunk/subversion/libsvn_client/export.c
subversion/trunk/subversion/tests/cmdline/export_tests.py
Modified: subversion/trunk/subversion/libsvn_client/export.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/export.c?rev=1575525&r1=1575524&r2=1575525&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/export.c (original)
+++ subversion/trunk/subversion/libsvn_client/export.c Sat Mar 8 11:42:48 2014
@@ -172,6 +172,7 @@ struct export_info_baton
void *notify_baton;
const char *origin_abspath;
svn_boolean_t exported;
+ svn_boolean_t exporting_external;
};
/* Export a file or directory. Implements svn_wc_status_func4_t */
@@ -268,7 +269,7 @@ export_node(void *baton,
scratch_pool));
}
- if (status->file_external)
+ if (status->file_external && !eib->exporting_external)
return SVN_NO_ERROR;
/* Produce overwrite errors for the export root */
@@ -1364,23 +1365,20 @@ export_directory(const char *from_path_o
return SVN_NO_ERROR;
}
-
-
-/*** Public Interfaces ***/
-
-svn_error_t *
-svn_client_export5(svn_revnum_t *result_rev,
- const char *from_path_or_url,
- const char *to_path,
- const svn_opt_revision_t *peg_revision,
- const svn_opt_revision_t *revision,
- svn_boolean_t overwrite,
- svn_boolean_t ignore_externals,
- svn_boolean_t ignore_keywords,
- svn_depth_t depth,
- const char *native_eol,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+static svn_error_t *
+do_export(svn_revnum_t *result_rev,
+ const char *from_path_or_url,
+ const char *to_path,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
+ svn_boolean_t overwrite,
+ svn_boolean_t ignore_externals,
+ svn_boolean_t ignore_keywords,
+ svn_depth_t depth,
+ const char *native_eol,
+ svn_boolean_t exporting_external,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
{
svn_revnum_t edit_revision = SVN_INVALID_REVNUM;
svn_boolean_t from_is_url = svn_path_is_url(from_path_or_url);
@@ -1511,6 +1509,7 @@ svn_client_export5(svn_revnum_t *result_
eib.notify_baton = ctx->notify_baton2;
eib.origin_abspath = from_path_or_url;
eib.exported = FALSE;
+ eib.exporting_external = exporting_external;
SVN_ERR(svn_wc_walk_status(ctx->wc_ctx, from_path_or_url, depth,
TRUE /* get_all */,
@@ -1558,15 +1557,15 @@ svn_client_export5(svn_revnum_t *result_
svn_dirent_dirname(target_abspath, iterpool),
iterpool));
- SVN_ERR(svn_client_export5(NULL,
- svn_dirent_join(from_path_or_url,
- relpath,
- iterpool),
- target_abspath,
- peg_revision, revision,
- TRUE, ignore_externals,
- ignore_keywords, depth, native_eol,
- ctx, iterpool));
+ SVN_ERR(do_export(NULL,
+ svn_dirent_join(from_path_or_url,
+ relpath,
+ iterpool),
+ target_abspath,
+ peg_revision, revision,
+ TRUE, ignore_externals,
+ ignore_keywords, depth, native_eol,
+ TRUE, ctx, iterpool));
}
svn_pool_destroy(iterpool);
@@ -1588,3 +1587,25 @@ svn_client_export5(svn_revnum_t *result_
return SVN_NO_ERROR;
}
+
+
+/*** Public Interfaces ***/
+svn_error_t *
+svn_client_export5(svn_revnum_t *result_rev,
+ const char *from_path_or_url,
+ const char *to_path,
+ const svn_opt_revision_t *peg_revision,
+ const svn_opt_revision_t *revision,
+ svn_boolean_t overwrite,
+ svn_boolean_t ignore_externals,
+ svn_boolean_t ignore_keywords,
+ svn_depth_t depth,
+ const char *native_eol,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(do_export(result_rev, from_path_or_url, to_path,
+ peg_revision, revision, overwrite,
+ ignore_externals, ignore_keywords,
+ depth, native_eol, FALSE, ctx, pool));
+}
Modified: subversion/trunk/subversion/tests/cmdline/export_tests.py
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/export_tests.py?rev=1575525&r1=1575524&r2=1575525&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/export_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/export_tests.py Sat Mar 8
11:42:48 2014
@@ -964,6 +964,59 @@ def export_custom_keywords(sbox):
if open(export_file).read() != ''.join(alpha_content):
raise svntest.Failure("wrong keyword expansion")
+@Issue(4427)
+def export_file_external(sbox):
+ "export file external from WC and URL"
+ sbox.build()
+
+ wc_dir = sbox.wc_dir
+
+ # Set 'svn:externals' property in 'A/C' to 'A/B/E/alpha'(file external),
+ C_path = os.path.join(wc_dir, 'A', 'C')
+ externals_prop = "^/A/B/E/alpha exfile_alpha"
+
+ tmp_f = sbox.get_tempname('prop')
+ svntest.main.file_append(tmp_f, externals_prop)
+ svntest.main.run_svn(None, 'ps', '-F', tmp_f, 'svn:externals', C_path)
+ svntest.main.run_svn(None,'ci', '-m', 'log msg', '--quiet', C_path)
+
+ # 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"),
+ })
+
+ # Export from URL
+ export_target = sbox.add_wc_path('export_url')
+ expected_output = svntest.main.greek_state.copy()
+ expected_output.add({
+ 'A/C/exfile_alpha' : Item("This is the file 'alpha'.\r"),
+ })
+ expected_output.wc_dir = export_target
+ expected_output.desc[''] = Item()
+ expected_output.tweak(contents=None, status='A ')
+ svntest.actions.run_and_verify_export(sbox.repo_url,
+ export_target,
+ expected_output,
+ expected_disk)
+
+ # Export from WC
+ export_target = sbox.add_wc_path('export_wc')
+ expected_output = svntest.main.greek_state.copy()
+ expected_output.add({
+ 'A/C/exfile_alpha' : Item("This is the file 'alpha'.\r"),
+ })
+ expected_output.wc_dir = export_target
+ expected_output.desc['A'] = Item()
+ expected_output.tweak(contents=None, status='A ')
+ svntest.actions.run_and_verify_export(wc_dir,
+ export_target,
+ expected_output,
+ expected_disk)
+
########################################################################
# Run the tests
@@ -998,6 +1051,7 @@ test_list = [ None,
export_to_current_dir,
export_file_overwrite_with_force,
export_custom_keywords,
+ export_file_external,
]
if __name__ == '__main__':