You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2012/08/16 12:18:03 UTC
svn commit: r1373783 [9/50] - in /subversion/branches/compressed-pristines:
./ build/ build/ac-macros/ build/generator/ build/generator/templates/
build/win32/ contrib/client-side/emacs/ contrib/client-side/svn-push/
contrib/client-side/svnmerge/ contr...
Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/externals.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/externals.c Thu Aug 16 10:17:48 2012
@@ -24,7 +24,7 @@
/* ==================================================================== */
-
+
/*** Includes. ***/
#include <apr_uri.h>
@@ -41,18 +41,7 @@
#include "svn_private_config.h"
#include "private/svn_wc_private.h"
-
-/* Closure for handle_external_item_change. */
-struct external_change_baton_t
-{
- /* The URL for the repository root. */
- const char *repos_root_url;
-
- /* Passed through to svn_client_* functions. */
- svn_client_ctx_t *ctx;
-
- svn_boolean_t *timestamp_sleep;
-};
+
/* Remove the directory at LOCAL_ABSPATH from revision control, and do the
* same to any revision controlled directories underneath LOCAL_ABSPATH
@@ -70,11 +59,16 @@ relegate_dir_external(svn_wc_context_t *
const char *local_abspath,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
apr_pool_t *scratch_pool)
{
svn_error_t *err = SVN_NO_ERROR;
- err = svn_wc__external_remove(wc_ctx, wri_abspath, local_abspath,
+ SVN_ERR(svn_wc__acquire_write_lock(NULL, wc_ctx, local_abspath,
+ FALSE, scratch_pool, scratch_pool));
+
+ err = svn_wc__external_remove(wc_ctx, wri_abspath, local_abspath, FALSE,
cancel_func, cancel_baton, scratch_pool);
if (err && (err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD))
{
@@ -114,8 +108,33 @@ relegate_dir_external(svn_wc_context_t *
/* Do our best, but no biggy if it fails. The rename will fail. */
svn_error_clear(svn_io_remove_file2(new_path, TRUE, scratch_pool));
- /* Rename. */
- SVN_ERR(svn_io_file_rename(local_abspath, new_path, scratch_pool));
+ /* Rename. If this is still a working copy we should use the working
+ copy rename function (to release open handles) */
+ err = svn_wc__rename_wc(wc_ctx, local_abspath, new_path,
+ scratch_pool);
+
+ if (err && err->apr_err == SVN_ERR_WC_PATH_UNEXPECTED_STATUS)
+ {
+ svn_error_clear(err);
+
+ /* And if it is no longer a working copy, we should just rename
+ it */
+ err = svn_io_file_rename(local_abspath, new_path, scratch_pool);
+ }
+
+ /* ### TODO: We should notify the user about the rename */
+ if (notify_func)
+ {
+ svn_wc_notify_t *notify;
+
+ notify = svn_wc_create_notify(err ? local_abspath : new_path,
+ svn_wc_notify_left_local_modifications,
+ scratch_pool);
+ notify->kind = svn_node_dir;
+ notify->err = err;
+
+ notify_func(notify_baton, notify, scratch_pool);
+ }
}
return svn_error_trace(err);
@@ -185,31 +204,45 @@ switch_dir_external(const char *local_ab
goto cleanup;
}
+ /* We'd really prefer not to have to do a brute-force
+ relegation -- blowing away the current external working
+ copy and checking it out anew -- so we'll first see if we
+ can get away with a generally cheaper relocation (if
+ required) and switch-style update.
+
+ To do so, we need to know the repository root URL of the
+ external working copy as it currently sits. */
SVN_ERR(svn_wc__node_get_repos_info(&repos_root_url, &repos_uuid,
ctx->wc_ctx, local_abspath,
pool, subpool));
if (repos_root_url)
{
- /* URLs don't match. Try to relocate (if necessary) and then
- switch. */
+ /* If the new external target URL is not obviously a
+ child of the external working copy's current
+ repository root URL... */
if (! svn_uri__is_ancestor(repos_root_url, url))
{
const char *repos_root;
svn_ra_session_t *ra_session;
- /* Get the repos root of the new URL. */
- SVN_ERR(svn_client__open_ra_session_internal
- (&ra_session, NULL, url, NULL, NULL,
- FALSE, TRUE, ctx, subpool));
+ /* ... then figure out precisely which repository
+ root URL that target URL *is* a child of ... */
+ SVN_ERR(svn_client__open_ra_session_internal(&ra_session,
+ NULL, url, NULL,
+ NULL, FALSE,
+ TRUE, ctx,
+ subpool));
SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root,
subpool));
+ /* ... and use that to try to relocate the external
+ working copy to the target location. */
err = svn_client_relocate2(local_abspath, repos_root_url,
- repos_root,
- FALSE, ctx, subpool);
- /* If the relocation failed because the new URL points
- to another repository, then we need to relegate and
- check out a new WC. */
+ repos_root, FALSE, ctx, subpool);
+
+ /* If the relocation failed because the new URL
+ points to a totally different repository, we've
+ no choice but to relegate and check out a new WC. */
if (err
&& (err->apr_err == SVN_ERR_WC_INVALID_RELOCATION
|| (err->apr_err
@@ -220,6 +253,10 @@ switch_dir_external(const char *local_ab
}
else if (err)
return svn_error_trace(err);
+
+ /* If the relocation went without a hitch, we should
+ have a new repository root URL. */
+ repos_root_url = repos_root;
}
SVN_ERR(svn_client__switch_internal(NULL, local_abspath, url,
@@ -258,12 +295,10 @@ switch_dir_external(const char *local_ab
if (kind == svn_node_dir)
{
/* Buh-bye, old and busted ... */
- SVN_ERR(svn_wc__acquire_write_lock(NULL, ctx->wc_ctx, local_abspath,
- FALSE, pool, pool));
-
SVN_ERR(relegate_dir_external(ctx->wc_ctx, defining_abspath,
local_abspath,
ctx->cancel_func, ctx->cancel_baton,
+ ctx->notify_func2, ctx->notify_baton2,
pool));
}
else
@@ -313,10 +348,6 @@ switch_file_external(const char *local_a
const svn_opt_revision_t *revision,
const char *def_dir_abspath,
svn_ra_session_t *ra_session,
- const char *ra_session_url,
- svn_revnum_t ra_revnum,
- const char *repos_root_url,
- svn_boolean_t *timestamp_sleep,
svn_client_ctx_t *ctx,
apr_pool_t *scratch_pool)
{
@@ -437,8 +468,7 @@ switch_file_external(const char *local_a
void *report_baton;
const svn_delta_editor_t *switch_editor;
void *switch_baton;
- const char *switch_rev_url;
- const char *repos_uuid;
+ svn_client__pathrev_t *switch_loc;
svn_revnum_t revnum;
/* ### TODO: Provide the real definition path (now available in
### def_dir_abspath) after switching to the new externals store.
@@ -447,22 +477,21 @@ switch_file_external(const char *local_a
const char *definition_abspath = svn_dirent_dirname(local_abspath,subpool);
/* Open an RA session to 'source' URL */
- SVN_ERR(svn_client__ra_session_from_path(&ra_session, &revnum,
- &switch_rev_url,
- url, dir_abspath,
- peg_revision, revision,
- ctx, subpool));
+ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &switch_loc,
+ url, dir_abspath,
+ peg_revision, revision,
+ ctx, subpool));
- SVN_ERR(svn_ra_reparent(ra_session, url, subpool));
- SVN_ERR(svn_ra_get_uuid2(ra_session, &repos_uuid, subpool));
+ SVN_ERR(svn_ra_reparent(ra_session, svn_uri_dirname(url, subpool),
+ subpool));
SVN_ERR(svn_wc__get_file_external_editor(&switch_editor, &switch_baton,
&revnum, ctx->wc_ctx,
local_abspath,
definition_abspath /* wri */,
- switch_rev_url,
- repos_root_url,
- repos_uuid,
+ switch_loc->url,
+ switch_loc->repos_root_url,
+ switch_loc->repos_uuid,
use_commit_times,
diff3_cmd, preserved_exts,
definition_abspath /* def */,
@@ -477,16 +506,17 @@ switch_file_external(const char *local_a
/* Tell RA to do an update of URL+TARGET to REVISION; if we pass an
invalid revnum, that means RA will use the latest revision. */
- SVN_ERR(svn_ra_do_switch2(ra_session, &reporter, &report_baton, revnum,
- target, svn_depth_unknown, url,
- switch_editor, switch_baton, subpool));
-
- SVN_ERR(svn_wc__crawl_file_external(ctx->wc_ctx, local_abspath,
- reporter, report_baton,
- TRUE, use_commit_times,
- ctx->cancel_func, ctx->cancel_baton,
- ctx->notify_func2, ctx->notify_baton2,
- subpool));
+ SVN_ERR(svn_ra_do_switch2(ra_session, &reporter, &report_baton,
+ switch_loc->rev,
+ target, svn_depth_unknown, url,
+ switch_editor, switch_baton, subpool));
+
+ SVN_ERR(svn_wc__crawl_file_external(ctx->wc_ctx, local_abspath,
+ reporter, report_baton,
+ TRUE, use_commit_times,
+ ctx->cancel_func, ctx->cancel_baton,
+ ctx->notify_func2, ctx->notify_baton2,
+ subpool));
if (ctx->notify_func2)
{
@@ -512,7 +542,7 @@ cleanup:
}
static svn_error_t *
-handle_external_item_removal(const struct external_change_baton_t *eb,
+handle_external_item_removal(const svn_client_ctx_t *ctx,
const char *defining_abspath,
const char *local_abspath,
apr_pool_t *scratch_pool)
@@ -526,34 +556,33 @@ handle_external_item_removal(const struc
const char *lock_root_abspath = NULL;
/* local_abspath should be a wcroot or a file external */
- SVN_ERR(svn_wc_read_kind(&kind, eb->ctx->wc_ctx, local_abspath, FALSE,
+ SVN_ERR(svn_wc_read_kind(&kind, ctx->wc_ctx, local_abspath, FALSE,
scratch_pool));
- if (kind == svn_node_none)
- return SVN_NO_ERROR; /* It's neither... Nothing to remove */
-
- SVN_ERR(svn_wc_locked2(&lock_existed, NULL, eb->ctx->wc_ctx,
- local_abspath, scratch_pool));
-
- if (! lock_existed)
+ if (kind != svn_node_none)
{
- SVN_ERR(svn_wc__acquire_write_lock(&lock_root_abspath,
- eb->ctx->wc_ctx, local_abspath,
- FALSE,
- scratch_pool,
- scratch_pool));
+ SVN_ERR(svn_wc_locked2(&lock_existed, NULL, ctx->wc_ctx,
+ local_abspath, scratch_pool));
+
+ if (! lock_existed)
+ {
+ SVN_ERR(svn_wc__acquire_write_lock(&lock_root_abspath,
+ ctx->wc_ctx, local_abspath,
+ FALSE,
+ scratch_pool, scratch_pool));
+ }
}
/* We don't use relegate_dir_external() here, because we know that
nothing else in this externals description (at least) is
going to need this directory, and therefore it's better to
leave stuff where the user expects it. */
- err = svn_wc__external_remove(eb->ctx->wc_ctx, defining_abspath,
- local_abspath,
- eb->ctx->cancel_func, eb->ctx->cancel_baton,
+ err = svn_wc__external_remove(ctx->wc_ctx, defining_abspath,
+ local_abspath, (kind == svn_node_none),
+ ctx->cancel_func, ctx->cancel_baton,
scratch_pool);
- if (eb->ctx->notify_func2)
+ if (ctx->notify_func2)
{
svn_wc_notify_t *notify =
svn_wc_create_notify(local_abspath,
@@ -563,8 +592,18 @@ handle_external_item_removal(const struc
notify->kind = kind;
notify->err = err;
- (eb->ctx->notify_func2)(eb->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)
+ {
+ notify = svn_wc_create_notify(local_abspath,
+ svn_wc_notify_left_local_modifications,
+ scratch_pool);
+ notify->kind = svn_node_dir;
+ notify->err = err;
+
+ (ctx->notify_func2)(ctx->notify_baton2, notify, scratch_pool);
+ }
}
if (err && err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD)
@@ -577,7 +616,7 @@ handle_external_item_removal(const struc
/* Unlock if we acquired the lock */
if (lock_root_abspath != NULL)
{
- svn_error_t *err2 = svn_wc__release_write_lock(eb->ctx->wc_ctx,
+ svn_error_t *err2 = svn_wc__release_write_lock(ctx->wc_ctx,
lock_root_abspath,
scratch_pool);
@@ -594,23 +633,22 @@ handle_external_item_removal(const struc
}
static svn_error_t *
-handle_external_item_change(const struct external_change_baton_t *eb,
+handle_external_item_change(svn_client_ctx_t *ctx,
+ const char *repos_root_url,
const char *parent_dir_abspath,
const char *parent_dir_url,
const char *local_abspath,
const char *old_defining_abspath,
const svn_wc_external_item2_t *new_item,
+ svn_boolean_t *timestamp_sleep,
apr_pool_t *scratch_pool)
{
svn_ra_session_t *ra_session;
- svn_revnum_t ra_revnum;
- const char *ra_session_url;
- const char *repos_root_url;
- const char *repos_uuid;
+ svn_client__pathrev_t *new_loc;
const char *new_url;
svn_node_kind_t ext_kind;
- SVN_ERR_ASSERT(eb->repos_root_url && parent_dir_url);
+ SVN_ERR_ASSERT(repos_root_url && parent_dir_url);
SVN_ERR_ASSERT(new_item != NULL);
/* Don't bother to check status, since we'll get that for free by
@@ -621,35 +659,31 @@ handle_external_item_change(const struct
any pointers they have should also outlive the iterpool. */
SVN_ERR(svn_wc__resolve_relative_external_url(&new_url,
- new_item, eb->repos_root_url,
+ new_item, repos_root_url,
parent_dir_url,
scratch_pool, scratch_pool));
/* Determine if the external is a file or directory. */
/* Get the RA connection. */
- SVN_ERR(svn_client__ra_session_from_path(&ra_session,
- &ra_revnum,
- &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, &repos_uuid, scratch_pool));
- SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url, scratch_pool));
- SVN_ERR(svn_ra_check_path(ra_session, "", ra_revnum, &ext_kind,
+ 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));
if (svn_node_none == ext_kind)
return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
_("URL '%s' at revision %ld doesn't exist"),
- ra_session_url, ra_revnum);
+ new_loc->url, new_loc->rev);
if (svn_node_dir != ext_kind && svn_node_file != ext_kind)
return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
_("URL '%s' at revision %ld is not a file "
"or a directory"),
- ra_session_url, ra_revnum);
+ new_loc->url, new_loc->rev);
/* Not protecting against recursive externals. Detecting them in
@@ -657,10 +691,10 @@ handle_external_item_change(const struct
user when it happens. Worst case: your disk fills up :-). */
/* First notify that we're about to handle an external. */
- if (eb->ctx->notify_func2)
+ if (ctx->notify_func2)
{
- (*eb->ctx->notify_func2)(
- eb->ctx->notify_baton2,
+ (*ctx->notify_func2)(
+ ctx->notify_baton2,
svn_wc_create_notify(local_abspath,
svn_wc_notify_update_external,
scratch_pool),
@@ -683,11 +717,11 @@ handle_external_item_change(const struct
&(new_item->peg_revision),
&(new_item->revision),
parent_dir_abspath,
- eb->timestamp_sleep, eb->ctx,
+ timestamp_sleep, ctx,
scratch_pool));
break;
case svn_node_file:
- if (strcmp(eb->repos_root_url, repos_root_url))
+ if (strcmp(repos_root_url, new_loc->repos_root_url))
{
const char *local_repos_root_url;
const char *local_repos_uuid;
@@ -704,32 +738,28 @@ handle_external_item_change(const struct
SVN_ERR(svn_wc__node_get_repos_info(&local_repos_root_url,
&local_repos_uuid,
- eb->ctx->wc_ctx,
+ ctx->wc_ctx,
parent_dir_abspath,
scratch_pool, scratch_pool));
- ext_repos_relpath = svn_uri_skip_ancestor(repos_root_url,
+ ext_repos_relpath = svn_uri_skip_ancestor(new_loc->repos_root_url,
new_url, scratch_pool);
if (local_repos_uuid == NULL || local_repos_root_url == NULL ||
ext_repos_relpath == NULL ||
- strcmp(local_repos_uuid, repos_uuid) != 0)
+ strcmp(local_repos_uuid, new_loc->repos_uuid) != 0)
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);
+ new_url, repos_root_url);
new_url = svn_path_url_add_component2(local_repos_root_url,
ext_repos_relpath,
scratch_pool);
- SVN_ERR(svn_client__ra_session_from_path(&ra_session,
- &ra_revnum,
- &ra_session_url,
- new_url,
- NULL,
- &(new_item->peg_revision),
- &(new_item->revision),
- eb->ctx, scratch_pool));
- SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url,
- scratch_pool));
+ 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(switch_file_external(local_abspath,
@@ -738,12 +768,10 @@ handle_external_item_change(const struct
&new_item->revision,
parent_dir_abspath,
ra_session,
- ra_session_url,
- ra_revnum,
- repos_root_url,
- eb->timestamp_sleep, eb->ctx,
+ ctx,
scratch_pool));
break;
+
default:
SVN_ERR_MALFUNCTION();
break;
@@ -753,22 +781,21 @@ handle_external_item_change(const struct
}
static svn_error_t *
-wrap_external_error(const struct external_change_baton_t *eb,
+wrap_external_error(const svn_client_ctx_t *ctx,
const char *target_abspath,
svn_error_t *err,
apr_pool_t *scratch_pool)
{
if (err && err->apr_err != SVN_ERR_CANCELLED)
{
- if (eb->ctx->notify_func2)
+ if (ctx->notify_func2)
{
svn_wc_notify_t *notifier = svn_wc_create_notify(
target_abspath,
svn_wc_notify_failed_external,
scratch_pool);
notifier->err = err;
- eb->ctx->notify_func2(eb->ctx->notify_baton2, notifier,
- scratch_pool);
+ ctx->notify_func2(ctx->notify_baton2, notifier, scratch_pool);
}
svn_error_clear(err);
return SVN_NO_ERROR;
@@ -778,7 +805,9 @@ wrap_external_error(const struct externa
}
static svn_error_t *
-handle_externals_change(const struct external_change_baton_t *eb,
+handle_externals_change(svn_client_ctx_t *ctx,
+ const char *repos_root_url,
+ svn_boolean_t *timestamp_sleep,
const char *local_abspath,
const char *new_desc_text,
apr_hash_t *old_externals,
@@ -809,7 +838,7 @@ handle_externals_change(const struct ext
else
new_desc = NULL;
- SVN_ERR(svn_wc__node_get_url(&url, eb->ctx->wc_ctx, local_abspath,
+ SVN_ERR(svn_wc__node_get_url(&url, ctx->wc_ctx, local_abspath,
scratch_pool, iterpool));
SVN_ERR_ASSERT(url);
@@ -819,26 +848,42 @@ handle_externals_change(const struct ext
const char *old_defining_abspath;
svn_wc_external_item2_t *new_item;
const char *target_abspath;
+ svn_boolean_t under_root;
new_item = APR_ARRAY_IDX(new_desc, i, svn_wc_external_item2_t *);
svn_pool_clear(iterpool);
- if (eb->ctx->cancel_func)
- SVN_ERR(eb->ctx->cancel_func(eb->ctx->cancel_baton));
+ if (ctx->cancel_func)
+ SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
- target_abspath = svn_dirent_join(local_abspath, new_item->target_dir,
- iterpool);
+ SVN_ERR(svn_dirent_is_under_root(&under_root, &target_abspath,
+ local_abspath, new_item->target_dir,
+ iterpool));
+
+ if (! under_root)
+ {
+ return svn_error_createf(
+ SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
+ _("Path '%s' is not in the working copy"),
+ svn_dirent_local_style(
+ svn_dirent_join(local_abspath, new_item->target_dir,
+ iterpool),
+ iterpool));
+ }
old_defining_abspath = apr_hash_get(old_externals, target_abspath,
APR_HASH_KEY_STRING);
SVN_ERR(wrap_external_error(
- eb, target_abspath,
- handle_external_item_change(eb, local_abspath, url,
+ ctx, target_abspath,
+ handle_external_item_change(ctx,
+ repos_root_url,
+ local_abspath, url,
target_abspath,
old_defining_abspath,
new_item,
+ timestamp_sleep,
iterpool),
iterpool));
@@ -866,15 +911,9 @@ svn_client__handle_externals(apr_hash_t
apr_hash_t *old_external_defs;
apr_hash_index_t *hi;
apr_pool_t *iterpool;
- struct external_change_baton_t eb;
SVN_ERR_ASSERT(repos_root_url);
- eb.repos_root_url = repos_root_url;
- eb.ctx = ctx;
- eb.timestamp_sleep = timestamp_sleep;
-
-
iterpool = svn_pool_create(scratch_pool);
/* Parse the old externals. This part will be replaced by reading EXTERNALS
@@ -913,7 +952,8 @@ svn_client__handle_externals(apr_hash_t
}
}
- SVN_ERR(handle_externals_change(&eb, local_abspath,
+ SVN_ERR(handle_externals_change(ctx, repos_root_url, timestamp_sleep,
+ local_abspath,
desc_text, old_external_defs,
ambient_depth, requested_depth,
iterpool));
@@ -931,8 +971,8 @@ svn_client__handle_externals(apr_hash_t
svn_pool_clear(iterpool);
SVN_ERR(wrap_external_error(
- &eb, item_abspath,
- handle_external_item_removal(&eb, defining_abspath,
+ ctx, item_abspath,
+ handle_external_item_removal(ctx, defining_abspath,
item_abspath, iterpool),
iterpool));
@@ -979,17 +1019,12 @@ svn_client__export_externals(apr_hash_t
svn_client_ctx_t *ctx,
apr_pool_t *scratch_pool)
{
- struct external_change_baton_t eb = { 0 };
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
apr_pool_t *sub_iterpool = svn_pool_create(scratch_pool);
apr_hash_index_t *hi;
SVN_ERR_ASSERT(svn_dirent_is_absolute(to_abspath));
- eb.repos_root_url = repos_root_url;
- eb.ctx = ctx;
- eb.timestamp_sleep = timestamp_sleep;
-
for (hi = apr_hash_first(scratch_pool, externals);
hi;
hi = apr_hash_next(hi))
@@ -1019,13 +1054,26 @@ svn_client__export_externals(apr_hash_t
{
const char *item_abspath;
const char *new_url;
+ svn_boolean_t under_root;
svn_wc_external_item2_t *item = APR_ARRAY_IDX(items, i,
svn_wc_external_item2_t *);
svn_pool_clear(sub_iterpool);
- item_abspath = svn_dirent_join(local_abspath, item->target_dir,
- sub_iterpool);
+ SVN_ERR(svn_dirent_is_under_root(&under_root, &item_abspath,
+ local_abspath, item->target_dir,
+ sub_iterpool));
+
+ if (! under_root)
+ {
+ return svn_error_createf(
+ SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
+ _("Path '%s' is not in the working copy"),
+ svn_dirent_local_style(
+ svn_dirent_join(local_abspath, item->target_dir,
+ sub_iterpool),
+ sub_iterpool));
+ }
SVN_ERR(svn_wc__resolve_relative_external_url(&new_url, item,
repos_root_url,
@@ -1039,7 +1087,7 @@ svn_client__export_externals(apr_hash_t
sub_iterpool));
SVN_ERR(wrap_external_error(
- &eb, item_abspath,
+ ctx, item_abspath,
svn_client_export5(NULL, new_url, item_abspath,
&item->peg_revision,
&item->revision,
@@ -1060,7 +1108,7 @@ svn_client__export_externals(apr_hash_t
svn_error_t *
svn_client__do_external_status(svn_client_ctx_t *ctx,
- apr_hash_t *externals_new,
+ apr_hash_t *external_map,
svn_depth_t depth,
svn_boolean_t get_all,
svn_boolean_t update,
@@ -1070,102 +1118,60 @@ svn_client__do_external_status(svn_clien
apr_pool_t *pool)
{
apr_hash_index_t *hi;
- apr_pool_t *subpool = svn_pool_create(pool);
+ apr_pool_t *iterpool = svn_pool_create(pool);
/* Loop over the hash of new values (we don't care about the old
ones). This is a mapping of versioned directories to property
values. */
- for (hi = apr_hash_first(pool, externals_new);
+ for (hi = apr_hash_first(pool, external_map);
hi;
hi = apr_hash_next(hi))
{
- apr_array_header_t *exts;
- const char *path = svn__apr_hash_index_key(hi);
- const char *propval = svn__apr_hash_index_val(hi);
- apr_pool_t *iterpool;
- int i;
+ svn_node_kind_t external_kind;
+ const char *local_abspath = svn__apr_hash_index_key(hi);
+ const char *defining_abspath = svn__apr_hash_index_val(hi);
+ svn_node_kind_t kind;
+ svn_opt_revision_t opt_rev;
- /* Clear the subpool. */
- svn_pool_clear(subpool);
+ svn_pool_clear(iterpool);
- /* Parse the svn:externals property value. This results in a
- hash mapping subdirectories to externals structures. */
- SVN_ERR(svn_wc_parse_externals_description3(&exts, path, propval,
- FALSE, subpool));
+ /* Obtain information on the expected external. */
+ SVN_ERR(svn_wc__read_external_info(&external_kind, NULL, NULL, NULL,
+ &opt_rev.value.number,
+ ctx->wc_ctx, defining_abspath,
+ local_abspath, FALSE,
+ iterpool, iterpool));
- /* Make a sub-pool of SUBPOOL. */
- iterpool = svn_pool_create(subpool);
+ if (external_kind != svn_node_dir)
+ continue;
- /* Loop over the subdir array. */
- for (i = 0; exts && (i < exts->nelts); i++)
- {
- const char *fullpath;
- svn_wc_external_item2_t *external;
- svn_node_kind_t kind;
-
- svn_pool_clear(iterpool);
-
- external = APR_ARRAY_IDX(exts, i, svn_wc_external_item2_t *);
- fullpath = svn_dirent_join(path, external->target_dir, iterpool);
-
- /* If the external target directory doesn't exist on disk,
- just skip it. */
- SVN_ERR(svn_io_check_path(fullpath, &kind, iterpool));
- if (kind != svn_node_dir)
- continue;
-
- /* Tell the client we're starting an external status set. */
- if (ctx->notify_func2)
- (ctx->notify_func2)(
+ SVN_ERR(svn_io_check_path(local_abspath, &kind, iterpool));
+ if (kind != svn_node_dir)
+ continue;
+
+ if (SVN_IS_VALID_REVNUM(opt_rev.value.number))
+ opt_rev.kind = svn_opt_revision_number;
+ else
+ opt_rev.kind = svn_opt_revision_unspecified;
+
+ /* Tell the client we're starting an external status set. */
+ if (ctx->notify_func2)
+ ctx->notify_func2(
ctx->notify_baton2,
- svn_wc_create_notify(fullpath, svn_wc_notify_status_external,
+ svn_wc_create_notify(local_abspath,
+ svn_wc_notify_status_external,
iterpool), iterpool);
- /* And then do the status. */
- SVN_ERR(svn_client_status5(NULL, ctx, fullpath,
- &(external->revision),
- depth, get_all, update,
- no_ignore, FALSE, FALSE, NULL,
- status_func, status_baton,
- iterpool));
- }
+ /* And then do the status. */
+ SVN_ERR(svn_client_status5(NULL, ctx, local_abspath, &opt_rev, depth,
+ get_all, update, no_ignore, FALSE, FALSE,
+ NULL, status_func, status_baton,
+ iterpool));
}
/* Destroy SUBPOOL and (implicitly) ITERPOOL. */
- svn_pool_destroy(subpool);
-
- return SVN_NO_ERROR;
-}
-
-
-/* Implements the `svn_wc_externals_update_t' interface. */
-svn_error_t *
-svn_client__external_info_gatherer(void *baton,
- const char *local_abspath,
- const svn_string_t *old_value,
- const svn_string_t *new_value,
- svn_depth_t depth,
- apr_pool_t *scratch_pool)
-{
- svn_client__external_func_baton_t *efb = baton;
-
- local_abspath = apr_pstrdup(efb->result_pool, local_abspath);
-
- if (efb->externals_old != NULL && old_value != NULL)
- apr_hash_set(efb->externals_old, local_abspath, APR_HASH_KEY_STRING,
- apr_pstrndup(efb->result_pool,
- old_value->data, old_value->len));
-
- if (efb->externals_new != NULL && new_value != NULL)
- apr_hash_set(efb->externals_new, local_abspath, APR_HASH_KEY_STRING,
- apr_pstrndup(efb->result_pool,
- new_value->data, new_value->len));
-
- if (efb->ambient_depths != NULL)
- apr_hash_set(efb->ambient_depths, local_abspath, APR_HASH_KEY_STRING,
- svn_depth_to_word(depth));
+ svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
-
Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/info.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/info.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/info.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/info.c Thu Aug 16 10:17:48 2012
@@ -348,7 +348,10 @@ svn_client_info3(const char *abspath_or_
|| peg_revision->kind == svn_opt_revision_unspecified))
{
/* Do all digging in the working copy. */
- wc_info_receiver_baton_t b = { receiver, receiver_baton };
+ wc_info_receiver_baton_t b;
+
+ b.client_receiver_func = receiver;
+ b.client_receiver_baton = receiver_baton;
return svn_error_trace(
svn_wc__get_info(ctx->wc_ctx, abspath_or_url, depth,
fetch_excluded, fetch_actual_only, changelists,
Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/list.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/list.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/list.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/list.c Thu Aug 16 10:17:48 2012
@@ -237,9 +237,8 @@ svn_client_list2(const char *path_or_url
apr_pool_t *pool)
{
svn_ra_session_t *ra_session;
- svn_revnum_t rev;
+ svn_client__pathrev_t *loc;
svn_dirent_t *dirent;
- const char *url;
const char *fs_path;
svn_error_t *err;
apr_hash_t *locks;
@@ -249,20 +248,19 @@ svn_client_list2(const char *path_or_url
dirent_fields |= SVN_DIRENT_KIND;
/* Get an RA plugin for this filesystem object. */
- SVN_ERR(svn_client__ra_session_from_path(&ra_session, &rev,
- &url, path_or_url, NULL,
- peg_revision,
- revision, ctx, pool));
+ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
+ path_or_url, NULL,
+ peg_revision,
+ revision, ctx, pool));
- SVN_ERR(svn_ra__get_fspath_relative_to_root(ra_session, &fs_path, url,
- pool));
+ fs_path = svn_client__pathrev_fspath(loc, pool);
- SVN_ERR(ra_stat_compatible(ra_session, rev, &dirent, dirent_fields,
+ SVN_ERR(ra_stat_compatible(ra_session, loc->rev, &dirent, dirent_fields,
ctx, pool));
if (! dirent)
return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
_("URL '%s' non-existent in revision %ld"),
- url, rev);
+ loc->url, loc->rev);
/* Maybe get all locks under url. */
if (fetch_locks)
@@ -292,7 +290,7 @@ svn_client_list2(const char *path_or_url
&& (depth == svn_depth_files
|| depth == svn_depth_immediates
|| depth == svn_depth_infinity))
- SVN_ERR(get_dir_contents(dirent_fields, "", rev, ra_session, locks,
+ SVN_ERR(get_dir_contents(dirent_fields, "", loc->rev, ra_session, locks,
fs_path, depth, ctx, list_func, baton, pool));
return SVN_NO_ERROR;
Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/locking_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/locking_commands.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/locking_commands.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/locking_commands.c Thu Aug 16 10:17:48 2012
@@ -44,7 +44,7 @@
/* For use with store_locks_callback, below. */
struct lock_baton
{
- const char *base_path;
+ const char *base_dir_abspath;
apr_hash_t *urls_to_paths;
svn_client_ctx_t *ctx;
apr_pool_t *pool;
@@ -55,8 +55,8 @@ struct lock_baton
* BATON is a 'struct lock_baton *', PATH is the path being locked,
* and LOCK is the lock itself.
*
- * If BATON->base_path is not null, then this function either stores
- * the LOCK on REL_URL or removes any lock tokens from REL_URL
+ * If BATON->base_dir_abspath is not null, then this function either
+ * stores the LOCK on REL_URL or removes any lock tokens from REL_URL
* (depending on whether DO_LOCK is true or false respectively), but
* only if RA_ERR is null, or (in the unlock case) is something other
* than SVN_ERR_FS_LOCK_OWNER_MISMATCH.
@@ -86,20 +86,17 @@ store_locks_callback(void *baton,
notify->lock = lock;
notify->err = ra_err;
- if (lb->base_path)
+ if (lb->base_dir_abspath)
{
char *path = apr_hash_get(lb->urls_to_paths, rel_url,
APR_HASH_KEY_STRING);
const char *local_abspath;
- SVN_ERR(svn_dirent_get_absolute(&local_abspath,
- svn_dirent_join(lb->base_path,
- path, pool),
- pool));
+ local_abspath = svn_dirent_join(lb->base_dir_abspath, path, pool);
/* Notify a valid working copy path */
notify->path = local_abspath;
- notify->path_prefix = lb->base_path;
+ notify->path_prefix = lb->base_dir_abspath;
if (do_lock)
{
@@ -345,8 +342,9 @@ organize_lock_targets(const char **commo
{
svn_revnum_t *revnum;
revnum = apr_palloc(result_pool, sizeof(* revnum));
- SVN_ERR(svn_wc__node_get_base_rev(revnum, ctx->wc_ctx,
- abs_path, result_pool));
+ SVN_ERR(svn_wc__node_get_base(revnum, NULL, NULL, NULL,
+ ctx->wc_ctx, abs_path,
+ result_pool, iterpool));
apr_hash_set(rel_targets_ret, rel_url,
APR_HASH_KEY_STRING, revnum);
}
@@ -456,7 +454,7 @@ svn_client_lock(const apr_array_header_t
NULL, FALSE, FALSE,
ctx, pool));
- cb.base_path = base_dir;
+ cb.base_dir_abspath = base_dir_abspath;
cb.urls_to_paths = urls_to_paths;
cb.ctx = ctx;
cb.pool = pool;
@@ -503,7 +501,7 @@ svn_client_unlock(const apr_array_header
if (! base_dir && !break_lock)
SVN_ERR(fetch_tokens(ra_session, path_tokens, pool));
- cb.base_path = base_dir;
+ cb.base_dir_abspath = base_dir_abspath;
cb.urls_to_paths = urls_to_paths;
cb.ctx = ctx;
cb.pool = pool;
Modified: subversion/branches/compressed-pristines/subversion/libsvn_client/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/compressed-pristines/subversion/libsvn_client/log.c?rev=1373783&r1=1373782&r2=1373783&view=diff
==============================================================================
--- subversion/branches/compressed-pristines/subversion/libsvn_client/log.c (original)
+++ subversion/branches/compressed-pristines/subversion/libsvn_client/log.c Thu Aug 16 10:17:48 2012
@@ -90,37 +90,37 @@ copyfrom_info_receiver(svn_location_segm
}
svn_error_t *
-svn_client__get_copy_source(const char *path_or_url,
+svn_client__get_copy_source(const char **original_repos_relpath,
+ svn_revnum_t *original_revision,
+ const char *path_or_url,
const svn_opt_revision_t *revision,
- const char **copyfrom_path,
- svn_revnum_t *copyfrom_rev,
svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_error_t *err;
copyfrom_info_t copyfrom_info = { 0 };
- apr_pool_t *sesspool = svn_pool_create(pool);
+ apr_pool_t *sesspool = svn_pool_create(scratch_pool);
svn_ra_session_t *ra_session;
- svn_revnum_t at_rev;
- const char *at_url;
+ svn_client__pathrev_t *at_loc;
copyfrom_info.is_first = TRUE;
copyfrom_info.path = NULL;
copyfrom_info.rev = SVN_INVALID_REVNUM;
- copyfrom_info.pool = pool;
+ copyfrom_info.pool = result_pool;
- SVN_ERR(svn_client__ra_session_from_path(&ra_session, &at_rev, &at_url,
- path_or_url, NULL,
- revision, revision,
- ctx, sesspool));
+ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &at_loc,
+ path_or_url, NULL,
+ revision, revision,
+ ctx, sesspool));
/* Find the copy source. Walk the location segments to find the revision
at which this node was created (copied or added). */
- err = svn_ra_get_location_segments(ra_session, "", at_rev, at_rev,
+ err = svn_ra_get_location_segments(ra_session, "", at_loc->rev, at_loc->rev,
SVN_INVALID_REVNUM,
copyfrom_info_receiver, ©from_info,
- pool);
+ scratch_pool);
svn_pool_destroy(sesspool);
@@ -134,14 +134,14 @@ svn_client__get_copy_source(const char *
svn_error_clear(err);
err = SVN_NO_ERROR;
- *copyfrom_path = NULL;
- *copyfrom_rev = SVN_INVALID_REVNUM;
+ *original_repos_relpath = NULL;
+ *original_revision = SVN_INVALID_REVNUM;
}
return svn_error_trace(err);
}
- *copyfrom_path = copyfrom_info.path;
- *copyfrom_rev = copyfrom_info.rev;
+ *original_repos_relpath = copyfrom_info.path;
+ *original_revision = copyfrom_info.rev;
return SVN_NO_ERROR;
}
@@ -281,7 +281,6 @@ svn_client_log5(const apr_array_header_t
svn_ra_session_t *ra_session;
const char *url_or_path;
svn_boolean_t has_log_revprops;
- const char *actual_url;
apr_array_header_t *condensed_targets;
svn_opt_revision_t session_opt_rev;
const char *ra_target;
@@ -474,6 +473,8 @@ svn_client_log5(const apr_array_header_t
{
+ svn_client__pathrev_t *actual_loc;
+
/* If this is a revision type that requires access to the working copy,
* we use our initial target path to figure out where to root the RA
* session, otherwise we use our URL. */
@@ -483,7 +484,7 @@ svn_client_log5(const apr_array_header_t
else
ra_target = url_or_path;
- SVN_ERR(svn_client__ra_session_from_path(&ra_session, NULL, &actual_url,
+ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &actual_loc,
ra_target, NULL,
&peg_rev, &session_opt_rev,
ctx, pool));
@@ -497,7 +498,7 @@ svn_client_log5(const apr_array_header_t
/* Create ra session on first use */
rb.ra_session_pool = pool;
- rb.ra_session_url = actual_url;
+ rb.ra_session_url = actual_loc->url;
}
}