summaryrefslogtreecommitdiff
path: root/subversion/libsvn_client/upgrade.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_client/upgrade.c')
-rw-r--r--subversion/libsvn_client/upgrade.c267
1 files changed, 136 insertions, 131 deletions
diff --git a/subversion/libsvn_client/upgrade.c b/subversion/libsvn_client/upgrade.c
index 5677b1cf59b1d..741443af2ddc1 100644
--- a/subversion/libsvn_client/upgrade.c
+++ b/subversion/libsvn_client/upgrade.c
@@ -179,6 +179,122 @@ svn_client_upgrade(const char *path,
return SVN_NO_ERROR;
}
+/* Helper for upgrade_externals_from_properties: upgrades one external ITEM
+ in EXTERNALS_PARENT. Uses SCRATCH_POOL for temporary allocations. */
+static svn_error_t *
+upgrade_external_item(svn_client_ctx_t *ctx,
+ const char *externals_parent_abspath,
+ const char *externals_parent_url,
+ const char *externals_parent_repos_root_url,
+ svn_wc_external_item2_t *item,
+ struct repos_info_baton *info_baton,
+ apr_pool_t *scratch_pool)
+{
+ const char *resolved_url;
+ const char *external_abspath;
+ const char *repos_relpath;
+ const char *repos_root_url;
+ const char *repos_uuid;
+ svn_node_kind_t external_kind;
+ svn_revnum_t peg_revision;
+ svn_revnum_t revision;
+ svn_error_t *err;
+
+ external_abspath = svn_dirent_join(externals_parent_abspath,
+ item->target_dir,
+ scratch_pool);
+
+ SVN_ERR(svn_wc__resolve_relative_external_url(
+ &resolved_url,
+ item,
+ externals_parent_repos_root_url,
+ externals_parent_url,
+ scratch_pool, scratch_pool));
+
+ /* This is a hack. We only need to call svn_wc_upgrade() on external
+ * dirs, as file externals are upgraded along with their defining
+ * WC. Reading the kind will throw an exception on an external dir,
+ * saying that the wc must be upgraded. If it's a file, the lookup
+ * is done in an adm_dir belonging to the defining wc (which has
+ * already been upgraded) and no error is returned. If it doesn't
+ * exist (external that isn't checked out yet), we'll just get
+ * svn_node_none. */
+ err = svn_wc_read_kind2(&external_kind, ctx->wc_ctx,
+ external_abspath, TRUE, FALSE, scratch_pool);
+ if (err && err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
+ {
+ svn_error_clear(err);
+
+ SVN_ERR(svn_client_upgrade(external_abspath, ctx, scratch_pool));
+ }
+ else if (err)
+ return svn_error_trace(err);
+
+ /* The upgrade of any dir should be done now, get the now reliable
+ * kind. */
+ SVN_ERR(svn_wc_read_kind2(&external_kind, ctx->wc_ctx, external_abspath,
+ TRUE, FALSE, scratch_pool));
+
+ /* Update the EXTERNALS table according to the root URL,
+ * relpath and uuid known in the upgraded external WC. */
+
+ /* We should probably have a function that provides all three
+ * of root URL, repos relpath and uuid at once, but here goes... */
+
+ /* First get the relpath, as that returns SVN_ERR_WC_PATH_NOT_FOUND
+ * when the node is not present in the file system.
+ * svn_wc__node_get_repos_info() would try to derive the URL. */
+ SVN_ERR(svn_wc__node_get_repos_info(NULL,
+ &repos_relpath,
+ &repos_root_url,
+ &repos_uuid,
+ ctx->wc_ctx,
+ external_abspath,
+ scratch_pool, scratch_pool));
+
+ /* If we haven't got any information from the checked out external,
+ * or if the URL information mismatches the external's definition,
+ * ask fetch_repos_info() to find out the repos root. */
+ if (0 != strcmp(resolved_url,
+ svn_path_url_add_component2(repos_root_url,
+ repos_relpath,
+ scratch_pool)))
+ {
+ SVN_ERR(fetch_repos_info(&repos_root_url, &repos_uuid, info_baton,
+ resolved_url, scratch_pool, scratch_pool));
+
+ repos_relpath = svn_uri_skip_ancestor(repos_root_url,
+ resolved_url,
+ scratch_pool);
+
+ /* There's just the URL, no idea what kind the external is.
+ * That's fine, as the external isn't even checked out yet.
+ * The kind will be set during the next 'update'. */
+ external_kind = svn_node_unknown;
+ }
+
+ peg_revision = (item->peg_revision.kind == svn_opt_revision_number
+ ? item->peg_revision.value.number
+ : SVN_INVALID_REVNUM);
+
+ revision = (item->revision.kind == svn_opt_revision_number
+ ? item->revision.value.number
+ : SVN_INVALID_REVNUM);
+
+ SVN_ERR(svn_wc__upgrade_add_external_info(ctx->wc_ctx,
+ external_abspath,
+ external_kind,
+ externals_parent_abspath,
+ repos_relpath,
+ repos_root_url,
+ repos_uuid,
+ peg_revision,
+ revision,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *
upgrade_externals_from_properties(svn_client_ctx_t *ctx,
const char *local_abspath,
@@ -207,34 +323,32 @@ upgrade_externals_from_properties(svn_client_ctx_t *ctx,
hi = apr_hash_next(hi))
{
int i;
- const char *externals_parent_abspath;
const char *externals_parent_url;
const char *externals_parent_repos_root_url;
const char *externals_parent_repos_relpath;
- const char *externals_parent = apr_hash_this_key(hi);
+ const char *externals_parent_abspath = apr_hash_this_key(hi);
svn_string_t *external_desc = apr_hash_this_val(hi);
apr_array_header_t *externals_p;
svn_error_t *err;
svn_pool_clear(iterpool);
+
+ /* svn_client_propget5() has API promise to return absolute paths. */
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(externals_parent_abspath));
+
externals_p = apr_array_make(iterpool, 1,
sizeof(svn_wc_external_item2_t*));
/* In this loop, an error causes the respective externals definition, or
* the external (inner loop), to be skipped, so that upgrade carries on
* with the other externals. */
-
- err = svn_dirent_get_absolute(&externals_parent_abspath,
- externals_parent, iterpool);
-
- if (!err)
- err = svn_wc__node_get_repos_info(NULL,
- &externals_parent_repos_relpath,
- &externals_parent_repos_root_url,
- NULL,
- ctx->wc_ctx,
- externals_parent_abspath,
- iterpool, iterpool);
+ err = svn_wc__node_get_repos_info(NULL,
+ &externals_parent_repos_relpath,
+ &externals_parent_repos_root_url,
+ NULL,
+ ctx->wc_ctx,
+ externals_parent_abspath,
+ iterpool, iterpool);
if (!err)
externals_parent_url = svn_path_url_add_component2(
@@ -248,7 +362,7 @@ upgrade_externals_from_properties(svn_client_ctx_t *ctx,
if (err)
{
svn_wc_notify_t *notify =
- svn_wc_create_notify(externals_parent,
+ svn_wc_create_notify(externals_parent_abspath,
svn_wc_notify_failed_external,
scratch_pool);
notify->err = err;
@@ -265,130 +379,21 @@ upgrade_externals_from_properties(svn_client_ctx_t *ctx,
for (i = 0; i < externals_p->nelts; i++)
{
svn_wc_external_item2_t *item;
- const char *resolved_url;
- const char *external_abspath;
- const char *repos_relpath;
- const char *repos_root_url;
- const char *repos_uuid;
- svn_node_kind_t external_kind;
- svn_revnum_t peg_revision;
- svn_revnum_t revision;
item = APR_ARRAY_IDX(externals_p, i, svn_wc_external_item2_t*);
svn_pool_clear(iterpool2);
- external_abspath = svn_dirent_join(externals_parent_abspath,
- item->target_dir,
- iterpool2);
-
- err = svn_wc__resolve_relative_external_url(
- &resolved_url,
- item,
- externals_parent_repos_root_url,
- externals_parent_url,
- scratch_pool, scratch_pool);
- if (err)
- goto handle_error;
-
- /* This is a hack. We only need to call svn_wc_upgrade() on external
- * dirs, as file externals are upgraded along with their defining
- * WC. Reading the kind will throw an exception on an external dir,
- * saying that the wc must be upgraded. If it's a file, the lookup
- * is done in an adm_dir belonging to the defining wc (which has
- * already been upgraded) and no error is returned. If it doesn't
- * exist (external that isn't checked out yet), we'll just get
- * svn_node_none. */
- err = svn_wc_read_kind2(&external_kind, ctx->wc_ctx,
- external_abspath, TRUE, FALSE, iterpool2);
- if (err && err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
- {
- svn_error_clear(err);
+ err = upgrade_external_item(ctx, externals_parent_abspath,
+ externals_parent_url,
+ externals_parent_repos_root_url,
+ item, info_baton, iterpool2);
- err = svn_client_upgrade(external_abspath, ctx, iterpool2);
- if (err)
- goto handle_error;
- }
- else if (err)
- goto handle_error;
-
- /* The upgrade of any dir should be done now, get the now reliable
- * kind. */
- err = svn_wc_read_kind2(&external_kind, ctx->wc_ctx, external_abspath,
- TRUE, FALSE, iterpool2);
- if (err)
- goto handle_error;
-
- /* Update the EXTERNALS table according to the root URL,
- * relpath and uuid known in the upgraded external WC. */
-
- /* We should probably have a function that provides all three
- * of root URL, repos relpath and uuid at once, but here goes... */
-
- /* First get the relpath, as that returns SVN_ERR_WC_PATH_NOT_FOUND
- * when the node is not present in the file system.
- * svn_wc__node_get_repos_info() would try to derive the URL. */
- err = svn_wc__node_get_repos_info(NULL,
- &repos_relpath,
- &repos_root_url,
- &repos_uuid,
- ctx->wc_ctx,
- external_abspath,
- iterpool2, iterpool2);
- if (err)
- goto handle_error;
-
- /* If we haven't got any information from the checked out external,
- * or if the URL information mismatches the external's definition,
- * ask fetch_repos_info() to find out the repos root. */
- if (0 != strcmp(resolved_url,
- svn_path_url_add_component2(repos_root_url,
- repos_relpath,
- scratch_pool)))
- {
- err = fetch_repos_info(&repos_root_url,
- &repos_uuid,
- info_baton,
- resolved_url,
- scratch_pool, scratch_pool);
- if (err)
- goto handle_error;
-
- repos_relpath = svn_uri_skip_ancestor(repos_root_url,
- resolved_url,
- iterpool2);
-
- /* There's just the URL, no idea what kind the external is.
- * That's fine, as the external isn't even checked out yet.
- * The kind will be set during the next 'update'. */
- external_kind = svn_node_unknown;
- }
-
- if (err)
- goto handle_error;
-
- peg_revision = (item->peg_revision.kind == svn_opt_revision_number
- ? item->peg_revision.value.number
- : SVN_INVALID_REVNUM);
-
- revision = (item->revision.kind == svn_opt_revision_number
- ? item->revision.value.number
- : SVN_INVALID_REVNUM);
-
- err = svn_wc__upgrade_add_external_info(ctx->wc_ctx,
- external_abspath,
- external_kind,
- externals_parent,
- repos_relpath,
- repos_root_url,
- repos_uuid,
- peg_revision,
- revision,
- iterpool2);
-handle_error:
if (err)
{
svn_wc_notify_t *notify =
- svn_wc_create_notify(external_abspath,
+ svn_wc_create_notify(svn_dirent_join(externals_parent_abspath,
+ item->target_dir,
+ iterpool2),
svn_wc_notify_failed_external,
scratch_pool);
notify->err = err;