On Tue, Dec 27, 2011 at 03:28:48PM +0100, Stefan Sperling wrote:
> On Tue, Dec 27, 2011 at 03:13:34PM +0100, Thomas Krebs wrote:
> > I changed the property values to ^/... and now it is somewhat better but
> > there is still one referenced subproject that does not work! What can I
> > do here?
> 
> Well, for a start, you'll have to show us exactly what you're seeing.
> By now you should understand the drill with problem reports.
> We can read neither your mind nor your screen from over here :)
> 
> > But even though, I apparently won't be able to checkout or update to
> > older revisions any more...?
> 
> You'll need to either wait for a new 1.7 client which has a fix to work around
> the issue (no patch exists as of yet but IMO we'll have to fix this in a
> patch release eventually because this is clearly a regression), or use a
> 1.6 client to check out those older revisions, or change the repository
> history by adjusting the svn:externals properties in older revisions.
> The latter would require a dump/load cycle filtered through svndumptool
> which you can find here: http://svn.borg.ch/svndumptool/
> 
> > I'm getting somewhat nervous ...
> 
> Understandably. I'm sorry you're hitting this problem. It might take
> some time to be resolved (due to people being on holidays, new year's,
> etc.) but we'll try our best to provide a fix ASAP.

Hi again Thomas,

I've implemented a fix for this problem and nominated it for backport
to the 1.7.4 release. This didn't make 1.7.3 which was released today,
sorry about that.

I am including a patch against 1.7.3 below. Are you able to you try
this patch to see if it fixes the problem for you? That would be very
valuable. Thank you!


Index: subversion/libsvn_client/externals.c
===================================================================
--- subversion/libsvn_client/externals.c        (.../1.7.x)     (revision 
1243712)
+++ subversion/libsvn_client/externals.c        (.../1.7.x-issue4087)   
(revision 1243712)
@@ -811,6 +811,7 @@ handle_external_item_change(const struct external_
   svn_ra_session_t *ra_session;
   svn_client__ra_session_from_path_results ra_cache = { 0 };
   const char *new_url;
+  svn_node_kind_t kind;
 
   ra_cache.kind = svn_node_unknown;
 
@@ -829,43 +830,38 @@ handle_external_item_change(const struct external_
                                          parent_dir_url,
                                          scratch_pool, scratch_pool));
 
-  /* If the external is being checked out, exported or updated,
-     determine if the external is a file or directory. */
-  if (new_item)
-    {
-      svn_node_kind_t kind;
+  /* Determine if the external is a file or directory. */
+  /* Get the RA connection. */
+  SVN_ERR(svn_client__ra_session_from_path(&ra_session,
+                                           &ra_cache.ra_revnum,
+                                           &ra_cache.ra_session_url,
+                                           new_url, NULL,
+                                           &(new_item->peg_revision),
+                                           &(new_item->revision), eb->ctx,
+                                           scratch_pool));
 
-      /* Get the RA connection. */
-      SVN_ERR(svn_client__ra_session_from_path(&ra_session,
-                                               &ra_cache.ra_revnum,
-                                               &ra_cache.ra_session_url,
-                                               new_url, NULL,
-                                               &(new_item->peg_revision),
-                                               &(new_item->revision), eb->ctx,
-                                               scratch_pool));
+  SVN_ERR(svn_ra_get_uuid2(ra_session, &ra_cache.repos_uuid,
+                           scratch_pool));
+  SVN_ERR(svn_ra_get_repos_root2(ra_session, &ra_cache.repos_root_url,
+                                 scratch_pool));
+  SVN_ERR(svn_ra_check_path(ra_session, "", ra_cache.ra_revnum, &kind,
+                            scratch_pool));
 
-      SVN_ERR(svn_ra_get_uuid2(ra_session, &ra_cache.repos_uuid,
-                               scratch_pool));
-      SVN_ERR(svn_ra_get_repos_root2(ra_session, &ra_cache.repos_root_url,
-                                     scratch_pool));
-      SVN_ERR(svn_ra_check_path(ra_session, "", ra_cache.ra_revnum, &kind,
-                                scratch_pool));
+  if (svn_node_none == kind)
+    return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
+                             _("URL '%s' at revision %ld doesn't exist"),
+                             ra_cache.ra_session_url,
+                             ra_cache.ra_revnum);
 
-      if (svn_node_none == kind)
-        return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
-                                 _("URL '%s' at revision %ld doesn't exist"),
-                                 ra_cache.ra_session_url,
-                                 ra_cache.ra_revnum);
+  if (svn_node_dir != kind && svn_node_file != kind)
+    return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
+                             _("URL '%s' at revision %ld is not a file "
+                               "or a directory"),
+                             ra_cache.ra_session_url,
+                             ra_cache.ra_revnum);
 
-      if (svn_node_dir != kind && svn_node_file != kind)
-        return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
-                                 _("URL '%s' at revision %ld is not a file "
-                                   "or a directory"),
-                                 ra_cache.ra_session_url,
-                                 ra_cache.ra_revnum);
+  ra_cache.kind = kind;
 
-      ra_cache.kind = kind;
-    }
 
   /* Not protecting against recursive externals.  Detecting them in
      the global case is hard, and it should be pretty obvious to a
@@ -873,96 +869,95 @@ handle_external_item_change(const struct external_
 
   if (! old_defining_abspath)
     {
-      /* This branch is only used during a checkout or an export. */
+      /* The target dir might have multiple components.  Guarantee the path
+         leading down to the last component. */
+      SVN_ERR(svn_io_make_dir_recursively(svn_dirent_dirname(local_abspath,
+                                                             scratch_pool),
+                                          scratch_pool));
+    }
 
-      /* First notify that we're about to handle an external. */
-      if (eb->ctx->notify_func2)
-        (*eb->ctx->notify_func2)(
-           eb->ctx->notify_baton2,
-           svn_wc_create_notify(local_abspath, svn_wc_notify_update_external,
-                                scratch_pool), scratch_pool);
-
-      switch (ra_cache.kind)
-        {
-        case svn_node_dir:
-          /* The target dir might have multiple components.  Guarantee
-             the path leading down to the last component. */
-          SVN_ERR(svn_io_make_dir_recursively(svn_dirent_dirname(local_abspath,
-                                                                 scratch_pool),
-                                              scratch_pool));
-
-          SVN_ERR(switch_dir_external(
-                   local_abspath, new_url,
-                   &(new_item->peg_revision), &(new_item->revision),
-                   parent_dir_abspath, eb->timestamp_sleep, eb->ctx,
-                   scratch_pool));
-          break;
-        case svn_node_file:
-          SVN_ERR(switch_file_external(local_abspath,
-                                       new_url,
-                                       &new_item->peg_revision,
-                                       &new_item->revision,
-                                       parent_dir_abspath,
-                                       ra_session,
-                                       ra_cache.ra_session_url,
-                                       ra_cache.ra_revnum,
-                                       ra_cache.repos_root_url,
-                                       eb->timestamp_sleep, eb->ctx,
-                                       scratch_pool));
-          break;
-        default:
-          SVN_ERR_MALFUNCTION();
-          break;
-        }
-    }
-  else
+  switch (ra_cache.kind)
     {
-      /* This branch handles a definition change or simple update. */
+      case svn_node_dir:
+        SVN_ERR(switch_dir_external(local_abspath, new_url,
+                                    &(new_item->peg_revision),
+                                    &(new_item->revision),
+                                    parent_dir_abspath,
+                                    eb->timestamp_sleep, eb->ctx,
+                                    scratch_pool));
+        break;
+      case svn_node_file:
+        if (strcmp(eb->repos_root_url, ra_cache.repos_root_url) == 0)
+          {
+            SVN_ERR(switch_file_external(local_abspath,
+                                         new_url,
+                                         &new_item->peg_revision,
+                                         &new_item->revision,
+                                         parent_dir_abspath,
+                                         ra_session,
+                                         ra_cache.ra_session_url,
+                                         ra_cache.ra_revnum,
+                                         ra_cache.repos_root_url,
+                                         eb->timestamp_sleep, eb->ctx,
+                                         scratch_pool));
+          }
+        else
+          {
+            const char *repos_uuid;
+            const char *ext_repos_relpath;
+            
+            /* 
+             * The working copy library currently requires that all files
+             * in the working copy have the same repository root URL.
+             * The URL from the file external's definition differs from the
+             * one used by the working copy. As a workaround, replace the
+             * root URL portion of the file external's URL, after making
+             * sure both URLs point to the same repository. See issue #4087.
+             */
 
-      /* First notify that we're about to handle an external. */
-      if (eb->ctx->notify_func2)
-        {
-          svn_wc_notify_t *nt;
+            SVN_ERR(svn_client__ra_session_from_path(&ra_session,
+                                                     &ra_cache.ra_revnum,
+                                                     &ra_cache.ra_session_url,
+                                                     eb->repos_root_url,
+                                                     NULL,
+                                                     &(new_item->peg_revision),
+                                                     &(new_item->revision),
+                                                     eb->ctx, scratch_pool));
+            SVN_ERR(svn_ra_get_uuid2(ra_session, &repos_uuid,
+                                     scratch_pool));
+            ext_repos_relpath = svn_uri_skip_ancestor(ra_cache.repos_root_url,
+                                                      new_url, scratch_pool);
+            if (strcmp(repos_uuid, ra_cache.repos_uuid) != 0 ||
+                ext_repos_relpath == NULL)
+              return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+                        _("Unsupported external: url of file external '%s' "
+                          "is not in repository '%s'"),
+                        new_url, eb->repos_root_url);
 
-          nt = svn_wc_create_notify(local_abspath,
-                                    svn_wc_notify_update_external,
-                                    scratch_pool);
+            SVN_ERR(svn_ra_get_repos_root2(ra_session,
+                                           &ra_cache.repos_root_url,
+                                           scratch_pool));
+            new_url = svn_path_url_add_component2(ra_cache.repos_root_url,
+                                                  ext_repos_relpath,
+                                                  scratch_pool);
+            SVN_ERR(svn_ra_reparent(ra_session, new_url, scratch_pool));
+            SVN_ERR(switch_file_external(local_abspath,
+                                         new_url,
+                                         &new_item->peg_revision,
+                                         &new_item->revision,
+                                         parent_dir_abspath,
+                                         ra_session,
+                                         ra_cache.ra_session_url,
+                                         ra_cache.ra_revnum,
+                                         ra_cache.repos_root_url,
+                                         eb->timestamp_sleep, eb->ctx,
+                                         scratch_pool));
 
-          eb->ctx->notify_func2(eb->ctx->notify_baton2, nt, scratch_pool);
-        }
-
-      /* Either the URL changed, or the exact same item is present in
-         both hashes, and caller wants to update such unchanged items.
-         In the latter case, the call below will try to make sure that
-         the external really is a WC pointing to the correct
-         URL/revision. */
-      switch (ra_cache.kind)
-        {
-        case svn_node_dir:
-          SVN_ERR(switch_dir_external(local_abspath, new_url,
-                                      &(new_item->peg_revision),
-                                      &(new_item->revision),
-                                      parent_dir_abspath,
-                                      eb->timestamp_sleep, eb->ctx,
-                                      scratch_pool));
-          break;
-        case svn_node_file:
-          SVN_ERR(switch_file_external(local_abspath,
-                                       new_url,
-                                       &new_item->peg_revision,
-                                       &new_item->revision,
-                                       parent_dir_abspath,
-                                       ra_session,
-                                       ra_cache.ra_session_url,
-                                       ra_cache.ra_revnum,
-                                       ra_cache.repos_root_url,
-                                       eb->timestamp_sleep, eb->ctx,
-                                       scratch_pool));
-          break;
-        default:
-          SVN_ERR_MALFUNCTION();
-          break;
-        }
+          }
+        break;
+      default:
+        SVN_ERR_MALFUNCTION();
+        break;
     }
 
   return SVN_NO_ERROR;

Reply via email to