summaryrefslogtreecommitdiff
path: root/subversion/libsvn_client/externals.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_client/externals.c')
-rw-r--r--subversion/libsvn_client/externals.c174
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,