diff options
Diffstat (limited to 'subversion/libsvn_client/externals.c')
-rw-r--r-- | subversion/libsvn_client/externals.c | 174 |
1 files changed, 122 insertions, 52 deletions
diff --git a/subversion/libsvn_client/externals.c b/subversion/libsvn_client/externals.c index 52c236c..851b260 100644 --- a/subversion/libsvn_client/externals.c +++ b/subversion/libsvn_client/externals.c @@ -151,6 +151,7 @@ switch_dir_external(const char *local_abspath, const svn_opt_revision_t *revision, const char *defining_abspath, svn_boolean_t *timestamp_sleep, + svn_ra_session_t *ra_session, svn_client_ctx_t *ctx, apr_pool_t *pool) { @@ -170,7 +171,7 @@ switch_dir_external(const char *local_abspath, if (revision->kind == svn_opt_revision_number) external_rev = revision->value.number; - /* + /* * The code below assumes existing versioned paths are *not* part of * the external's defining working copy. * The working copy library does not support registering externals @@ -186,7 +187,6 @@ switch_dir_external(const char *local_abspath, &repos_root_url, &repos_uuid, NULL, ctx->wc_ctx, local_abspath, TRUE, /* ignore_enoent */ - TRUE, /* show hidden */ pool, pool)); if (kind != svn_node_unknown) { @@ -231,17 +231,53 @@ switch_dir_external(const char *local_abspath, if (node_url) { + svn_boolean_t is_wcroot; + + SVN_ERR(svn_wc__is_wcroot(&is_wcroot, ctx->wc_ctx, local_abspath, + pool)); + + if (! is_wcroot) + { + /* This can't be a directory external! */ + + err = svn_wc__external_remove(ctx->wc_ctx, defining_abspath, + local_abspath, + TRUE /* declaration_only */, + ctx->cancel_func, ctx->cancel_baton, + pool); + + if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) + { + /* New external... No problem that we can't remove it */ + svn_error_clear(err); + err = NULL; + } + else if (err) + return svn_error_trace(err); + + return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL, + _("The external '%s' defined in %s at '%s' " + "cannot be checked out because '%s' is " + "already a versioned path."), + url_from_externals_definition, + SVN_PROP_EXTERNALS, + svn_dirent_local_style(defining_abspath, + pool), + svn_dirent_local_style(local_abspath, + pool)); + } + /* If we have what appears to be a version controlled subdir, and its top-level URL matches that of our externals definition, perform an update. */ if (strcmp(node_url, url) == 0) { - SVN_ERR(svn_client__update_internal(NULL, local_abspath, + SVN_ERR(svn_client__update_internal(NULL, timestamp_sleep, + local_abspath, revision, svn_depth_unknown, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, - timestamp_sleep, - ctx, subpool)); + ra_session, ctx, subpool)); /* We just decided that this existing directory is an external, so update the external registry with this information, like @@ -372,9 +408,11 @@ switch_dir_external(const char *local_abspath, } /* ... Hello, new hotness. */ - SVN_ERR(svn_client__checkout_internal(NULL, url, local_abspath, peg_revision, + SVN_ERR(svn_client__checkout_internal(NULL, timestamp_sleep, + url, local_abspath, peg_revision, revision, svn_depth_infinity, - FALSE, FALSE, timestamp_sleep, + FALSE, FALSE, + ra_session, ctx, pool)); SVN_ERR(svn_wc__node_get_repos_info(NULL, NULL, @@ -401,14 +439,15 @@ switch_dir_external(const char *local_abspath, return SVN_NO_ERROR; } -/* Try to update a file external at LOCAL_ABSPATH to URL at REVISION using a - access baton that has a write lock. Use SCRATCH_POOL for temporary +/* Try to update a file external at LOCAL_ABSPATH to SWITCH_LOC. This function + assumes caller has a write lock in CTX. Use SCRATCH_POOL for temporary allocations, and use the client context CTX. */ static svn_error_t * switch_file_external(const char *local_abspath, - const char *url, - const svn_opt_revision_t *peg_revision, - const svn_opt_revision_t *revision, + const svn_client__pathrev_t *switch_loc, + const char *record_url, + const svn_opt_revision_t *record_peg_revision, + const svn_opt_revision_t *record_revision, const char *def_dir_abspath, svn_ra_session_t *ra_session, svn_client_ctx_t *ctx, @@ -485,7 +524,8 @@ switch_file_external(const char *local_abspath, SVN_ERR_CLIENT_FILE_EXTERNAL_OVERWRITE_VERSIONED, 0, _("The file external from '%s' cannot overwrite the existing " "versioned item at '%s'"), - url, svn_dirent_local_style(local_abspath, scratch_pool)); + switch_loc->url, + svn_dirent_local_style(local_abspath, scratch_pool)); } } else @@ -507,28 +547,17 @@ switch_file_external(const char *local_abspath, void *report_baton; const svn_delta_editor_t *switch_editor; void *switch_baton; - svn_client__pathrev_t *switch_loc; svn_revnum_t revnum; apr_array_header_t *inherited_props; - const char *dir_abspath; - const char *target; - - svn_dirent_split(&dir_abspath, &target, local_abspath, scratch_pool); - - /* ### Why do we open a new session? RA_SESSION is a valid - ### session -- the caller used it to call svn_ra_check_path on - ### this very URL, the caller also did the resolving and - ### reparenting that is repeated here. */ - SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &switch_loc, - url, dir_abspath, - peg_revision, revision, - ctx, scratch_pool)); + const char *target = svn_dirent_basename(local_abspath, scratch_pool); + /* Get the external file's iprops. */ SVN_ERR(svn_ra_get_inherited_props(ra_session, &inherited_props, "", switch_loc->rev, scratch_pool, scratch_pool)); - SVN_ERR(svn_ra_reparent(ra_session, svn_uri_dirname(url, scratch_pool), + SVN_ERR(svn_ra_reparent(ra_session, + svn_uri_dirname(switch_loc->url, scratch_pool), scratch_pool)); SVN_ERR(svn_wc__get_file_external_editor(&switch_editor, &switch_baton, @@ -542,9 +571,9 @@ switch_file_external(const char *local_abspath, use_commit_times, diff3_cmd, preserved_exts, def_dir_abspath, - url, peg_revision, revision, - ctx->conflict_func2, - ctx->conflict_baton2, + record_url, + record_peg_revision, + record_revision, ctx->cancel_func, ctx->cancel_baton, ctx->notify_func2, @@ -578,7 +607,7 @@ switch_file_external(const char *local_abspath, = svn_wc_notify_state_inapplicable; notify->lock_state = svn_wc_notify_lock_state_inapplicable; notify->revision = revnum; - (*ctx->notify_func2)(ctx->notify_baton2, notify, scratch_pool); + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); } } @@ -691,7 +720,7 @@ handle_external_item_removal(const svn_client_ctx_t *ctx, notify->kind = kind; notify->err = err; - (ctx->notify_func2)(ctx->notify_baton2, notify, scratch_pool); + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); if (err && err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD) { @@ -701,7 +730,7 @@ handle_external_item_removal(const svn_client_ctx_t *ctx, notify->kind = svn_node_dir; notify->err = err; - (ctx->notify_func2)(ctx->notify_baton2, notify, scratch_pool); + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); } } @@ -722,10 +751,10 @@ handle_external_item_change(svn_client_ctx_t *ctx, const char *local_abspath, const char *old_defining_abspath, const svn_wc_external_item2_t *new_item, + svn_ra_session_t *ra_session, svn_boolean_t *timestamp_sleep, apr_pool_t *scratch_pool) { - svn_ra_session_t *ra_session; svn_client__pathrev_t *new_loc; const char *new_url; svn_node_kind_t ext_kind; @@ -746,12 +775,39 @@ handle_external_item_change(svn_client_ctx_t *ctx, scratch_pool, scratch_pool)); /* Determine if the external is a file or directory. */ - /* Get the RA connection. */ - SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &new_loc, - new_url, NULL, - &(new_item->peg_revision), - &(new_item->revision), ctx, - scratch_pool)); + /* Get the RA connection, if needed. */ + if (ra_session) + { + svn_error_t *err = svn_ra_reparent(ra_session, new_url, scratch_pool); + + if (err) + { + if (err->apr_err == SVN_ERR_RA_ILLEGAL_URL) + { + svn_error_clear(err); + ra_session = NULL; + } + else + return svn_error_trace(err); + } + else + { + SVN_ERR(svn_client__resolve_rev_and_url(&new_loc, + ra_session, new_url, + &(new_item->peg_revision), + &(new_item->revision), ctx, + scratch_pool)); + + SVN_ERR(svn_ra_reparent(ra_session, new_loc->url, scratch_pool)); + } + } + + if (!ra_session) + SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &new_loc, + new_url, NULL, + &(new_item->peg_revision), + &(new_item->revision), ctx, + scratch_pool)); SVN_ERR(svn_ra_check_path(ra_session, "", new_loc->rev, &ext_kind, scratch_pool)); @@ -775,7 +831,7 @@ handle_external_item_change(svn_client_ctx_t *ctx, /* First notify that we're about to handle an external. */ if (ctx->notify_func2) { - (*ctx->notify_func2)( + ctx->notify_func2( ctx->notify_baton2, svn_wc_create_notify(local_abspath, svn_wc_notify_update_external, @@ -800,7 +856,7 @@ handle_external_item_change(svn_client_ctx_t *ctx, &(new_item->peg_revision), &(new_item->revision), parent_dir_abspath, - timestamp_sleep, ctx, + timestamp_sleep, ra_session, ctx, scratch_pool)); break; case svn_node_file: @@ -858,6 +914,7 @@ handle_external_item_change(svn_client_ctx_t *ctx, } SVN_ERR(switch_file_external(local_abspath, + new_loc, new_url, &new_item->peg_revision, &new_item->revision, @@ -908,6 +965,7 @@ handle_externals_change(svn_client_ctx_t *ctx, apr_hash_t *old_externals, svn_depth_t ambient_depth, svn_depth_t requested_depth, + svn_ra_session_t *ra_session, apr_pool_t *scratch_pool) { apr_array_header_t *new_desc; @@ -976,7 +1034,7 @@ handle_externals_change(svn_client_ctx_t *ctx, local_abspath, url, target_abspath, old_defining_abspath, - new_item, + new_item, ra_session, timestamp_sleep, iterpool), iterpool)); @@ -999,6 +1057,7 @@ svn_client__handle_externals(apr_hash_t *externals_new, const char *target_abspath, svn_depth_t requested_depth, svn_boolean_t *timestamp_sleep, + svn_ra_session_t *ra_session, svn_client_ctx_t *ctx, apr_pool_t *scratch_pool) { @@ -1018,8 +1077,8 @@ svn_client__handle_externals(apr_hash_t *externals_new, hi; hi = apr_hash_next(hi)) { - const char *local_abspath = svn__apr_hash_index_key(hi); - const char *desc_text = svn__apr_hash_index_val(hi); + const char *local_abspath = apr_hash_this_key(hi); + const char *desc_text = apr_hash_this_val(hi); svn_depth_t ambient_depth = svn_depth_infinity; svn_pool_clear(iterpool); @@ -1029,7 +1088,7 @@ svn_client__handle_externals(apr_hash_t *externals_new, const char *ambient_depth_w; ambient_depth_w = apr_hash_get(ambient_depths, local_abspath, - svn__apr_hash_index_klen(hi)); + apr_hash_this_key_len(hi)); if (ambient_depth_w == NULL) { @@ -1048,7 +1107,7 @@ svn_client__handle_externals(apr_hash_t *externals_new, local_abspath, desc_text, old_external_defs, ambient_depth, requested_depth, - iterpool)); + ra_session, iterpool)); } /* Remove the remaining externals */ @@ -1056,8 +1115,8 @@ svn_client__handle_externals(apr_hash_t *externals_new, hi; hi = apr_hash_next(hi)) { - const char *item_abspath = svn__apr_hash_index_key(hi); - const char *defining_abspath = svn__apr_hash_index_val(hi); + const char *item_abspath = apr_hash_this_key(hi); + const char *defining_abspath = apr_hash_this_val(hi); const char *parent_abspath; svn_pool_clear(iterpool); @@ -1131,8 +1190,8 @@ svn_client__export_externals(apr_hash_t *externals, hi; hi = apr_hash_next(hi)) { - const char *local_abspath = svn__apr_hash_index_key(hi); - const char *desc_text = svn__apr_hash_index_val(hi); + const char *local_abspath = apr_hash_this_key(hi); + const char *desc_text = apr_hash_this_val(hi); const char *local_relpath; const char *dir_url; apr_array_header_t *items; @@ -1188,6 +1247,17 @@ svn_client__export_externals(apr_hash_t *externals, sub_iterpool), sub_iterpool)); + /* First notify that we're about to handle an external. */ + if (ctx->notify_func2) + { + ctx->notify_func2( + ctx->notify_baton2, + svn_wc_create_notify(item_abspath, + svn_wc_notify_update_external, + sub_iterpool), + sub_iterpool); + } + SVN_ERR(wrap_external_error( ctx, item_abspath, svn_client_export5(NULL, new_url, item_abspath, |