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;