This 'check via explicit target’ would also fix calling 'svn export’ directly on a file external, which is probably still broken after this patch.
Bert
Sent from Windows Mail
From: Bert Huijben
Sent: Saturday, March 8, 2014 8:55 PM
To: commits_at_subversion.apache.org, dev_at_subversion.apache.org
This version doesn't support exporting file externals inside directory externals as in that case the same external will exported as file in the working copy *and* as external after the working copy.
And then overwriting the file that already exists fails.
That is why I recommended that you should keep the root (its abspath) in the baton instead of a boolean. As that is the only proper way to get this working recursively. (passing force overwrite for externals for the other problem would be an ugly hack)
Bert
Sent from Windows Mail
From: Stefan Sperling
Sent: Saturday, March 8, 2014 12:42 PM
To: commits_at_subversion.apache.org
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__':
Received on 2014-03-08 21:55:39 CET