Hi!

The message from Stefan Sperling is copy-pasted from another thread that
refers to this one.

Comments inline, new log message at bottom.

On Thu, Dec 17, 2009 at 10:39:06PM +0100, Stefan Sperling wrote:
> On Thu, Dec 17, 2009 at 08:40:15PM +0100, Daniel Näslund wrote:
> > Hi!
> > 
> > NOTE: This patch depends on my patch for #3390 that has not been
> > commited yet [1]. The external_func uses abspaths and that is fixed in
> > the referred patch. I have two more patches that depend on [1].
> > 
> > make check passes with [1] applied.
> 
> I'm travelling, and because I am being disorganised I don't have [1]
> in my mailbox right now. So I cannot reply there. Sorry about messing
> up the threading.
> 
> Reviewing [1]:
> 
> > @@ -1193,19 +1196,30 @@
> >    ib.pool              = cb->pool;
> >    ib.iter_pool         = svn_pool_create(cb->pool);
> >  
> > -  /* Get the URL of the parent directory by appending a portion of
> > -     parent_dir to from_url.  from_url is the URL for to_path and
> > -     to_path is a substring of parent_dir, so append any characters in
> > -     parent_dir past strlen(to_path) to from_url (making sure to move
> > -     past a '/' in parent_dir, otherwise svn_path_url_add_component()
> > -     will error. */
> > -  len = strlen(cb->to_path);
> > -  if (ib.parent_dir[len] == '/')
> > -    ++len;
> > -  ib.parent_dir_url = svn_path_url_add_component2(cb->from_url,
> > -                                                  ib.parent_dir + len,
> > -                                                  cb->pool);
> > +  SVN_ERR(svn_dirent_get_absolute(&abs_parent_dir, ib.parent_dir, 
> > +                                  cb->pool));
> >  
> > +  err = svn_wc__node_get_url(&url, cb->ctx->wc_ctx, 
> > +                             abs_parent_dir, cb->pool, cb->pool);
> > +  ib.parent_dir_url = url;
> 
> I'd rather put "ib.parent_dir_url = url;" into a final 'else' clause
> of the following if statement.
> 
> > +
> > +  if (err)
> > +    {
> > +      /* Get the URL of the parent directory by appending a portion of
> > +         parent_dir to from_url.  from_url is the URL for to_path and
> > +         to_path is a substring of parent_dir, so append any characters in
> > +         parent_dir past strlen(to_path) to from_url (making sure to move
> > +         past a '/' in parent_dir, otherwise svn_path_url_add_component()
> > +         will error. */
> > +      len = strlen(cb->to_path);
> > +      if (ib.parent_dir[len] == '/')
> > +        ++len;
> > +      ib.parent_dir_url = svn_path_url_add_component2(cb->from_url,
> > +                                                      ib.parent_dir + len,
> > +                                                      cb->pool);
> > +      svn_error_clear(err);
> > +    }

Fixed.

> 
> The above ignores any error returned from svn_wc__node_get_url().
> Usually, we only ignore specific errors, and pass others back to the caller.
> The idiom goes like this:
> 
> if (err)
>   {
>     if (err->apr_err == ...)
>       {
>         /* ignore this */
>       svn_error_clear(err);
>       }
>     else
>       SVN_ERR(err);
>   }
> 
> Any reason why you made this code ignore all errors?

I got assertions about some paths not beeing absolute. So until all
callers use absolute paths I catch all errors. I've added a note about
this in the code. 

[[[
Fix issue #3390, relative externals not updated during switch.

* subversion/libsvn_client/switch.c
  (svn_client__switch_internal): Pass in an external_func to
    svn_wc_crawl_revision5().

* subversion/libsvn_client/externals.c
  (handle_externals_desc_change): Get the url for parent_dir with
    svn_wc__node_get_url(). Does not work for export where the
    parent_dir has no url. Then we resort to the old way of adding the
    parent_dir to the from_url.

* subversion/tests/cmdline/externals_tests.py
  (test_list): Remove XFail from switch_relative_external.

Patch by: Daniel Näslund <daniel{_AT_}longitudo.com>
Review by: stsp
]]]

Index: subversion/tests/cmdline/externals_tests.py
===================================================================
--- subversion/tests/cmdline/externals_tests.py	(revision 892468)
+++ subversion/tests/cmdline/externals_tests.py	(arbetskopia)
@@ -1583,7 +1583,7 @@
               external_into_path_with_spaces,
               binary_file_externals,
               XFail(update_lose_file_external),
-              XFail(switch_relative_external),
+              switch_relative_external,
               export_sparse_wc_with_externals,
               relegate_external,
               wc_repos_file_externals,
Index: subversion/libsvn_client/switch.c
===================================================================
--- subversion/libsvn_client/switch.c	(revision 892468)
+++ subversion/libsvn_client/switch.c	(arbetskopia)
@@ -256,13 +256,15 @@
      PATH.  When we call reporter->finish_report, the update_editor
      will be driven by svn_repos_dir_delta2.
 
-     We pass NULL for traversal_info because this is a switch, not an
-     update, and therefore we don't want to handle any externals
-     except the ones directly affected by the switch. */
+     We pass in an external_func for recording all externals. It
+     shouldn't be needed for a switch if it wasn't for the relative
+     externals of type '../path'. All of those must be resolved to 
+     the new location.  */
   err = svn_wc_crawl_revisions5(ctx->wc_ctx, local_abspath, reporter,
                                 report_baton, TRUE, depth, (! depth_is_sticky),
                                 (! server_supports_depth),
-                                use_commit_times, NULL, NULL,
+                                use_commit_times, 
+                                svn_client__external_info_gatherer, &efb,
                                 ctx->notify_func2, ctx->notify_baton2, pool);
 
   if (err)
Index: subversion/libsvn_client/externals.c
===================================================================
--- subversion/libsvn_client/externals.c	(revision 892468)
+++ subversion/libsvn_client/externals.c	(arbetskopia)
@@ -1115,6 +1115,9 @@
   int i;
   svn_wc_external_item2_t *item;
   const char *ambient_depth_w;
+  const char *url;
+  const char *abs_parent_dir;
+  svn_error_t *err;
   svn_depth_t ambient_depth;
 
   if (cb->is_export)
@@ -1193,19 +1196,38 @@
   ib.pool              = cb->pool;
   ib.iter_pool         = svn_pool_create(cb->pool);
 
-  /* Get the URL of the parent directory by appending a portion of
-     parent_dir to from_url.  from_url is the URL for to_path and
-     to_path is a substring of parent_dir, so append any characters in
-     parent_dir past strlen(to_path) to from_url (making sure to move
-     past a '/' in parent_dir, otherwise svn_path_url_add_component()
-     will error. */
-  len = strlen(cb->to_path);
-  if (ib.parent_dir[len] == '/')
-    ++len;
-  ib.parent_dir_url = svn_path_url_add_component2(cb->from_url,
-                                                  ib.parent_dir + len,
-                                                  cb->pool);
+  SVN_ERR(svn_dirent_get_absolute(&abs_parent_dir, ib.parent_dir, 
+                                  cb->pool));
 
+  /* First try to get the associated url and if there is none as is the case
+   * for exports then do use the user supplied values. */
+  err = svn_wc__node_get_url(&url, cb->ctx->wc_ctx, 
+                             abs_parent_dir, cb->pool, cb->pool);
+
+  /* We want to check for just SVN_ERR_WC_PATH_NOT_FOUND here but since not
+   * all callers use absolute paths at the moment we get assertions about
+   * that, which we must catch. */
+  if (err)
+    {
+      /* Get the URL of the parent directory by appending a portion of
+         parent_dir to from_url.  from_url is the URL for to_path and
+         to_path is a substring of parent_dir, so append any characters in
+         parent_dir past strlen(to_path) to from_url (making sure to move
+         past a '/' in parent_dir, otherwise svn_path_url_add_component()
+         will error. */
+      len = strlen(cb->to_path);
+      if (ib.parent_dir[len] == '/')
+        ++len;
+      ib.parent_dir_url = svn_path_url_add_component2(cb->from_url,
+                                                      ib.parent_dir + len,
+                                                      cb->pool);
+      svn_error_clear(err);
+    }
+  else
+    {
+      ib.parent_dir_url = url;
+    }
+
   /* We must use a custom version of svn_hash_diff so that the diff
      entries are processed in the order they were originally specified
      in the svn:externals properties. */

Reply via email to