You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2014/03/08 12:42:48 UTC

svn commit: r1575525 - in /subversion/trunk/subversion: libsvn_client/export.c tests/cmdline/export_tests.py

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__':



Re: svn commit: r1575525 - in /subversion/trunk/subversion: libsvn_client/export.c tests/cmdline/export_tests.py

Posted by Stefan Sperling <st...@elego.de>.
On Mon, Mar 10, 2014 at 03:25:16PM +0100, Bert Huijben wrote:
> > -----Original Message-----
> > From: Stefan Sperling [mailto:stsp@elego.de]
> > Sent: maandag 10 maart 2014 14:54
> > To: Bert Huijben
> > Cc: commits@subversion.apache.org; dev@subversion.apache.org
> > Subject: Re: svn commit: r1575525 - in /subversion/trunk/subversion:
> > libsvn_client/export.c tests/cmdline/export_tests.py
> > 
> > On Sat, Mar 08, 2014 at 08:53:39PM +0000, Bert Huijben wrote:
> > > This 'check via explicit target’ would also fix calling 'svn export’ directly on a
> > file external, which is probably still broken after this patch.
> > >
> > 
> > Thanks for fixing it in r1575915 :)
> > 
> > I figured that a lazy "fix" of mine would make you take another look
> > at this code ;)
> 
> Thanks ;-)
> 
> I also added a nomination for 1.8.x. Do you know if this also needs a backport for 1.7?
> 
> 	Bert

1.7.x seems to work fine in my simple testing. It exports a single
file external properly.

Re: svn commit: r1575525 - in /subversion/trunk/subversion: libsvn_client/export.c tests/cmdline/export_tests.py

Posted by Stefan Sperling <st...@elego.de>.
On Mon, Mar 10, 2014 at 03:25:16PM +0100, Bert Huijben wrote:
> > -----Original Message-----
> > From: Stefan Sperling [mailto:stsp@elego.de]
> > Sent: maandag 10 maart 2014 14:54
> > To: Bert Huijben
> > Cc: commits@subversion.apache.org; dev@subversion.apache.org
> > Subject: Re: svn commit: r1575525 - in /subversion/trunk/subversion:
> > libsvn_client/export.c tests/cmdline/export_tests.py
> > 
> > On Sat, Mar 08, 2014 at 08:53:39PM +0000, Bert Huijben wrote:
> > > This 'check via explicit target’ would also fix calling 'svn export’ directly on a
> > file external, which is probably still broken after this patch.
> > >
> > 
> > Thanks for fixing it in r1575915 :)
> > 
> > I figured that a lazy "fix" of mine would make you take another look
> > at this code ;)
> 
> Thanks ;-)
> 
> I also added a nomination for 1.8.x. Do you know if this also needs a backport for 1.7?
> 
> 	Bert

1.7.x seems to work fine in my simple testing. It exports a single
file external properly.

RE: svn commit: r1575525 - in /subversion/trunk/subversion: libsvn_client/export.c tests/cmdline/export_tests.py

Posted by Bert Huijben <be...@qqmail.nl>.
> -----Original Message-----
> From: Stefan Sperling [mailto:stsp@elego.de]
> Sent: maandag 10 maart 2014 14:54
> To: Bert Huijben
> Cc: commits@subversion.apache.org; dev@subversion.apache.org
> Subject: Re: svn commit: r1575525 - in /subversion/trunk/subversion:
> libsvn_client/export.c tests/cmdline/export_tests.py
> 
> On Sat, Mar 08, 2014 at 08:53:39PM +0000, Bert Huijben wrote:
> > This 'check via explicit target’ would also fix calling 'svn export’ directly on a
> file external, which is probably still broken after this patch.
> >
> 
> Thanks for fixing it in r1575915 :)
> 
> I figured that a lazy "fix" of mine would make you take another look
> at this code ;)

Thanks ;-)

I also added a nomination for 1.8.x. Do you know if this also needs a backport for 1.7?

	Bert


RE: svn commit: r1575525 - in /subversion/trunk/subversion: libsvn_client/export.c tests/cmdline/export_tests.py

Posted by Bert Huijben <be...@qqmail.nl>.
> -----Original Message-----
> From: Stefan Sperling [mailto:stsp@elego.de]
> Sent: maandag 10 maart 2014 14:54
> To: Bert Huijben
> Cc: commits@subversion.apache.org; dev@subversion.apache.org
> Subject: Re: svn commit: r1575525 - in /subversion/trunk/subversion:
> libsvn_client/export.c tests/cmdline/export_tests.py
> 
> On Sat, Mar 08, 2014 at 08:53:39PM +0000, Bert Huijben wrote:
> > This 'check via explicit target’ would also fix calling 'svn export’ directly on a
> file external, which is probably still broken after this patch.
> >
> 
> Thanks for fixing it in r1575915 :)
> 
> I figured that a lazy "fix" of mine would make you take another look
> at this code ;)

Thanks ;-)

I also added a nomination for 1.8.x. Do you know if this also needs a backport for 1.7?

	Bert


Re: svn commit: r1575525 - in /subversion/trunk/subversion: libsvn_client/export.c tests/cmdline/export_tests.py

Posted by Stefan Sperling <st...@elego.de>.
On Sat, Mar 08, 2014 at 08:53:39PM +0000, Bert Huijben wrote:
> This 'check via explicit target’ would also fix calling 'svn export’ directly on a file external, which is probably still broken after this patch.
> 

Thanks for fixing it in r1575915 :)

I figured that a lazy "fix" of mine would make you take another look
at this code ;)

Re: svn commit: r1575525 - in /subversion/trunk/subversion: libsvn_client/export.c tests/cmdline/export_tests.py

Posted by Stefan Sperling <st...@elego.de>.
On Sat, Mar 08, 2014 at 08:53:39PM +0000, Bert Huijben wrote:
> This 'check via explicit target’ would also fix calling 'svn export’ directly on a file external, which is probably still broken after this patch.
> 

Thanks for fixing it in r1575915 :)

I figured that a lazy "fix" of mine would make you take another look
at this code ;)

Re: svn commit: r1575525 - in /subversion/trunk/subversion: libsvn_client/export.c tests/cmdline/export_tests.py

Posted by Bert Huijben <be...@qqmail.nl>.
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@subversion.apache.org, dev@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@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__':

Re: svn commit: r1575525 - in /subversion/trunk/subversion: libsvn_client/export.c tests/cmdline/export_tests.py

Posted by Bert Huijben <be...@qqmail.nl>.
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@subversion.apache.org, dev@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@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__':

Re: svn commit: r1575525 - in /subversion/trunk/subversion: libsvn_client/export.c tests/cmdline/export_tests.py

Posted by Bert Huijben <be...@qqmail.nl>.
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@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__':

Re: svn commit: r1575525 - in /subversion/trunk/subversion: libsvn_client/export.c tests/cmdline/export_tests.py

Posted by Bert Huijben <be...@qqmail.nl>.
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@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__':