You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/09/28 19:35:26 UTC
svn commit: r1002283 [3/10] - in /subversion/branches/javahl-ra: ./ build/
notes/ notes/http-and-webdav/ notes/wc-ng/ subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/apache/subversion/javahl/
subversion/bindings/javahl/src/org/tig...
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/commit.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/commit.c Tue Sep 28 17:35:22 2010
@@ -109,6 +109,10 @@ typedef struct {
apr_hash_t *changed_props;
apr_hash_t *removed_props;
+ /* Same, for the old value (*old_value_p). */
+ apr_hash_t *previous_changed_props;
+ apr_hash_t *previous_removed_props;
+
/* In HTTP v2, this is the file/directory version we think we're changing. */
svn_revnum_t base_revision;
@@ -639,16 +643,17 @@ checkout_file(file_context_t *file)
/* Helper function for proppatch_walker() below. */
static svn_error_t *
get_encoding_and_cdata(const char **encoding_p,
- serf_bucket_t **cdata_bkt_p,
+ const svn_string_t **encoded_value_p,
serf_bucket_alloc_t *alloc,
const svn_string_t *value,
apr_pool_t *pool)
{
- const char *encoding;
- const char *cdata;
- apr_size_t len; /* of cdata */
-
- SVN_ERR_ASSERT(value);
+ if (value == NULL)
+ {
+ *encoding_p = NULL;
+ *encoded_value_p = NULL;
+ return SVN_NO_ERROR;
+ }
/* If a property is XML-safe, XML-encode it. Else, base64-encode
it. */
@@ -656,23 +661,72 @@ get_encoding_and_cdata(const char **enco
{
svn_stringbuf_t *xml_esc = NULL;
svn_xml_escape_cdata_string(&xml_esc, value, pool);
- encoding = NULL;
- cdata = xml_esc->data;
- len = xml_esc->len;
+ *encoding_p = NULL;
+ *encoded_value_p = svn_string_create_from_buf(xml_esc, pool);
}
else
{
- const svn_string_t *base64ed = svn_base64_encode_string2(value, TRUE,
- pool);
- encoding = "base64";
- cdata = base64ed->data;
- len = base64ed->len;
+ *encoding_p = "base64";
+ *encoded_value_p = svn_base64_encode_string2(value, TRUE, pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+typedef struct walker_baton_t {
+ serf_bucket_t *body_bkt;
+ apr_hash_t *previous_changed_props;
+ apr_hash_t *previous_removed_props;
+ const char *path;
+
+ /* Hack, since change_rev_prop(old_value_p != NULL, value = NULL) uses D:set
+ rather than D:remove... (see notes/http-and-webdav/webdav-protocol) */
+ enum {
+ filter_all_props,
+ filter_props_with_old_value,
+ filter_props_without_old_value
+ } filter;
+
+ /* Is the property being deleted? */
+ svn_boolean_t deleting;
+} walker_baton_t;
+
+static svn_error_t *
+derive_old_val(const svn_string_t *const * *old_val_p_p,
+ walker_baton_t *wb,
+ const char *ns,
+ const char *name,
+ apr_pool_t *pool)
+{
+ const svn_string_t *const *old_val_p;
+
+ old_val_p = NULL;
+
+ if (wb->previous_changed_props)
+ {
+ const svn_string_t *old_val;
+ old_val = svn_ra_serf__get_prop_string(wb->previous_changed_props,
+ wb->path, ns, name);
+ if (old_val)
+ {
+ old_val_p = apr_pcalloc(pool, sizeof(*old_val_p));
+ *(const svn_string_t **)old_val_p = svn_string_dup(old_val, pool);
+ }
}
- /* ENCODING, CDATA, and LEN are now set. */
+ if (wb->previous_removed_props)
+ {
+ const svn_string_t *old_val;
+ old_val = svn_ra_serf__get_prop_string(wb->previous_removed_props,
+ wb->path, ns, name);
+ if (old_val)
+ {
+ old_val_p = apr_pcalloc(pool, sizeof(*old_val_p));
+ *(const svn_string_t **)old_val_p = NULL;
+ }
+ }
- *encoding_p = encoding;
- *cdata_bkt_p = SERF_BUCKET_SIMPLE_STRING_LEN(cdata, len, alloc);
+ *old_val_p_p = old_val_p;
return SVN_NO_ERROR;
}
@@ -683,10 +737,13 @@ proppatch_walker(void *baton,
const svn_string_t *val,
apr_pool_t *pool)
{
- serf_bucket_t *body_bkt = baton;
+ walker_baton_t *wb = baton;
+ serf_bucket_t *body_bkt = wb->body_bkt;
serf_bucket_t *cdata_bkt;
serf_bucket_alloc_t *alloc;
const char *encoding;
+ const svn_string_t *const *old_val_p;
+ const svn_string_t *encoded_value;
char *prop_name;
/* Use the namespace prefix instead of adding the xmlns attribute to support
@@ -697,14 +754,82 @@ proppatch_walker(void *baton,
prop_name = apr_pstrcat(pool, "C:", name, NULL);
name_len = strlen(prop_name);
+ SVN_ERR(derive_old_val(&old_val_p, wb, ns, name, pool));
+
+ /* Jump through hoops to work with D:remove and its val = (""-for-NULL)
+ * representation. */
+ if (wb->filter != filter_all_props)
+ {
+ if (wb->filter == filter_props_with_old_value && ! old_val_p)
+ return SVN_NO_ERROR;
+ if (wb->filter == filter_props_without_old_value && old_val_p)
+ return SVN_NO_ERROR;
+ }
+ if (wb->deleting)
+ val = NULL;
+
alloc = body_bkt->allocator;
- SVN_ERR(get_encoding_and_cdata(&encoding, &cdata_bkt, alloc, val, pool));
+ SVN_ERR(get_encoding_and_cdata(&encoding, &encoded_value, alloc, val, pool));
+ if (encoded_value)
+ {
+ cdata_bkt = SERF_BUCKET_SIMPLE_STRING_LEN(encoded_value->data,
+ encoded_value->len,
+ alloc);
+ }
+ else
+ {
+ cdata_bkt = NULL;
+ }
- svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, prop_name,
- "V:encoding", encoding,
- NULL);
- serf_bucket_aggregate_append(body_bkt, cdata_bkt);
+ if (cdata_bkt)
+ svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, prop_name,
+ "V:encoding", encoding,
+ NULL);
+ else
+ svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, prop_name,
+ "V:" SVN_DAV__OLD_VALUE__ABSENT, "1",
+ NULL);
+
+ if (old_val_p)
+ {
+ const char *encoding2;
+ const svn_string_t *encoded_value2;
+ serf_bucket_t *cdata_bkt2;
+
+ SVN_ERR(get_encoding_and_cdata(&encoding2, &encoded_value2,
+ alloc, *old_val_p, pool));
+
+ if (encoded_value2)
+ {
+ cdata_bkt2 = SERF_BUCKET_SIMPLE_STRING_LEN(encoded_value2->data,
+ encoded_value2->len,
+ alloc);
+ }
+ else
+ {
+ cdata_bkt2 = NULL;
+ }
+
+ if (cdata_bkt2)
+ svn_ra_serf__add_open_tag_buckets(body_bkt, alloc,
+ "V:" SVN_DAV__OLD_VALUE,
+ "V:encoding", encoding2,
+ NULL);
+ else
+ svn_ra_serf__add_open_tag_buckets(body_bkt, alloc,
+ "V:" SVN_DAV__OLD_VALUE,
+ "V:" SVN_DAV__OLD_VALUE__ABSENT, "1",
+ NULL);
+
+ if (cdata_bkt2)
+ serf_bucket_aggregate_append(body_bkt, cdata_bkt2);
+
+ svn_ra_serf__add_close_tag_buckets(body_bkt, alloc,
+ "V:" SVN_DAV__OLD_VALUE);
+ }
+ if (cdata_bkt)
+ serf_bucket_aggregate_append(body_bkt, cdata_bkt);
svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, prop_name);
return SVN_NO_ERROR;
@@ -753,6 +878,7 @@ create_proppatch_body(serf_bucket_t **bk
{
proppatch_context_t *ctx = baton;
serf_bucket_t *body_bkt;
+ walker_baton_t *wb;
body_bkt = serf_bucket_aggregate_create(alloc);
@@ -764,14 +890,37 @@ create_proppatch_body(serf_bucket_t **bk
"xmlns:S", SVN_DAV_PROP_NS_SVN,
NULL);
+ wb = apr_pcalloc(pool, sizeof(*wb));
+ wb->body_bkt = body_bkt;
+ wb->previous_changed_props = ctx->previous_changed_props;
+ wb->previous_removed_props = ctx->previous_removed_props;
+ wb->path = ctx->path;
+
if (apr_hash_count(ctx->changed_props) > 0)
{
svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:set", NULL);
svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:prop", NULL);
+ wb->filter = filter_all_props;
+ wb->deleting = FALSE;
SVN_ERR(svn_ra_serf__walk_all_props(ctx->changed_props, ctx->path,
SVN_INVALID_REVNUM,
- proppatch_walker, body_bkt, pool));
+ proppatch_walker, wb, pool));
+
+ svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:prop");
+ svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:set");
+ }
+
+ if (apr_hash_count(ctx->removed_props) > 0)
+ {
+ svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:set", NULL);
+ svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:prop", NULL);
+
+ wb->filter = filter_props_with_old_value;
+ wb->deleting = TRUE;
+ SVN_ERR(svn_ra_serf__walk_all_props(ctx->removed_props, ctx->path,
+ SVN_INVALID_REVNUM,
+ proppatch_walker, wb, pool));
svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:prop");
svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:set");
@@ -782,9 +931,11 @@ create_proppatch_body(serf_bucket_t **bk
svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:remove", NULL);
svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:prop", NULL);
+ wb->filter = filter_props_without_old_value;
+ wb->deleting = TRUE;
SVN_ERR(svn_ra_serf__walk_all_props(ctx->removed_props, ctx->path,
SVN_INVALID_REVNUM,
- proppatch_walker, body_bkt, pool));
+ proppatch_walker, wb, pool));
svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:prop");
svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:remove");
@@ -2208,6 +2359,7 @@ svn_error_t *
svn_ra_serf__change_rev_prop(svn_ra_session_t *ra_session,
svn_revnum_t rev,
const char *name,
+ const svn_string_t *const *old_value_p,
const svn_string_t *value,
apr_pool_t *pool)
{
@@ -2219,6 +2371,17 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
apr_hash_t *props;
svn_error_t *err;
+ if (old_value_p)
+ {
+ svn_boolean_t capable;
+ SVN_ERR(svn_ra_serf__has_capability(ra_session, &capable,
+ SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+ pool));
+
+ /* How did you get past the same check in svn_ra_change_rev_prop2()? */
+ SVN_ERR_ASSERT(capable);
+ }
+
commit = apr_pcalloc(pool, sizeof(*commit));
commit->pool = pool;
@@ -2265,8 +2428,28 @@ svn_ra_serf__change_rev_prop(svn_ra_sess
proppatch_ctx->path = proppatch_target;
proppatch_ctx->changed_props = apr_hash_make(proppatch_ctx->pool);
proppatch_ctx->removed_props = apr_hash_make(proppatch_ctx->pool);
+ if (old_value_p)
+ {
+ proppatch_ctx->previous_changed_props = apr_hash_make(proppatch_ctx->pool);
+ proppatch_ctx->previous_removed_props = apr_hash_make(proppatch_ctx->pool);
+ }
proppatch_ctx->base_revision = SVN_INVALID_REVNUM;
+ if (old_value_p && *old_value_p)
+ {
+ svn_ra_serf__set_prop(proppatch_ctx->previous_changed_props,
+ proppatch_ctx->path,
+ ns, name, *old_value_p, proppatch_ctx->pool);
+ }
+ else if (old_value_p)
+ {
+ svn_string_t *dummy_value = svn_string_create("", proppatch_ctx->pool);
+
+ svn_ra_serf__set_prop(proppatch_ctx->previous_removed_props,
+ proppatch_ctx->path,
+ ns, name, dummy_value, proppatch_ctx->pool);
+ }
+
if (value)
{
svn_ra_serf__set_prop(proppatch_ctx->changed_props, proppatch_ctx->path,
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/options.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/options.c Tue Sep 28 17:35:22 2010
@@ -313,6 +313,13 @@ capabilities_headers_iterator_callback(v
SVN_RA_CAPABILITY_LOG_REVPROPS,
APR_HASH_KEY_STRING, capability_yes);
}
+ if (svn_cstring_match_glob_list(SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS,
+ vals))
+ {
+ apr_hash_set(orc->session->capabilities,
+ SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+ APR_HASH_KEY_STRING, capability_yes);
+ }
if (svn_cstring_match_glob_list(SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY, vals))
{
apr_hash_set(orc->session->capabilities,
@@ -404,6 +411,8 @@ options_response_handler(serf_request_t
APR_HASH_KEY_STRING, capability_no);
apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS,
APR_HASH_KEY_STRING, capability_no);
+ apr_hash_set(orc->session->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+ APR_HASH_KEY_STRING, capability_no);
/* Then see which ones we can discover. */
serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback, orc);
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/ra_serf.h?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/ra_serf.h Tue Sep 28 17:35:22 2010
@@ -673,6 +673,9 @@ typedef struct svn_ra_serf__server_error
/* Have we seen an error tag? */
svn_boolean_t in_error;
+ /* Have we seen a HTTP "412 Precondition Failed" error? */
+ svn_boolean_t contains_precondition_error;
+
/* Should we be collecting the XML cdata? */
svn_boolean_t collect_cdata;
@@ -1322,6 +1325,7 @@ svn_error_t *
svn_ra_serf__change_rev_prop(svn_ra_session_t *session,
svn_revnum_t rev,
const char *name,
+ const svn_string_t *const *old_value_p,
const svn_string_t *value,
apr_pool_t *pool);
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/replay.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/replay.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/replay.c Tue Sep 28 17:35:22 2010
@@ -90,7 +90,7 @@ typedef struct {
replay_info_t *parent;
} prop_info_t;
-typedef struct {
+typedef struct replay_context_t {
apr_pool_t *src_rev_pool;
apr_pool_t *dst_rev_pool;
@@ -118,6 +118,10 @@ typedef struct {
/* Cached report target url */
const char *report_target;
+ /* Target and revision to fetch revision properties on */
+ const char *revprop_target;
+ svn_revnum_t revprop_rev;
+
/* Revision properties for this revision. */
apr_hash_t *revs_props;
apr_hash_t *props;
@@ -125,6 +129,9 @@ typedef struct {
/* Keep a reference to the XML parser ctx to report any errors. */
svn_ra_serf__xml_parser_t *parser_ctx;
+ /* The propfind for the revision properties of the current revision */
+ svn_ra_serf__propfind_context_t *prop_ctx;
+
} replay_context_t;
@@ -180,11 +187,15 @@ start_replay(svn_ra_serf__xml_parser_t *
{
push_state(parser, ctx, REPORT);
+ /* Before we can continue, we need the revision properties. */
+ SVN_ERR_ASSERT(!ctx->prop_ctx
+ || svn_ra_serf__propfind_is_done(ctx->prop_ctx));
+
/* Create a pool for the commit editor. */
ctx->dst_rev_pool = svn_pool_create(ctx->src_rev_pool);
ctx->props = apr_hash_make(ctx->dst_rev_pool);
- SVN_ERR(svn_ra_serf__walk_all_props(ctx->revs_props, ctx->report_target,
- ctx->revision,
+ SVN_ERR(svn_ra_serf__walk_all_props(ctx->revs_props, ctx->revprop_target,
+ ctx->revprop_rev,
svn_ra_serf__set_bare_props,
ctx->props, ctx->dst_rev_pool));
if (ctx->revstart_func)
@@ -751,13 +762,30 @@ svn_ra_serf__replay_range(svn_ra_session
/* Request all properties of a certain revision. */
replay_ctx->report_target = report_target;
replay_ctx->revs_props = apr_hash_make(replay_ctx->src_rev_pool);
+
+ if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session))
+ {
+ replay_ctx->revprop_target = apr_psprintf(pool, "%s/%ld",
+ session->rev_stub, rev);
+ replay_ctx->revprop_rev = SVN_INVALID_REVNUM;
+ }
+ else
+ {
+ replay_ctx->revprop_target = report_target;
+ replay_ctx->revprop_rev = rev;
+ }
+
SVN_ERR(svn_ra_serf__deliver_props(&prop_ctx,
replay_ctx->revs_props, session,
- session->conns[0], report_target,
- rev, "0", all_props,
+ session->conns[0],
+ replay_ctx->revprop_target,
+ replay_ctx->revprop_rev,
+ "0", all_props,
TRUE, NULL,
replay_ctx->src_rev_pool));
+ replay_ctx->prop_ctx = prop_ctx;
+
/* Send the replay report request. */
handler = apr_pcalloc(replay_ctx->src_rev_pool, sizeof(*handler));
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/util.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/util.c Tue Sep 28 17:35:22 2010
@@ -836,6 +836,7 @@ svn_ra_serf__handle_discard_body(serf_re
{
server_err->error = svn_error_create(APR_SUCCESS, NULL, NULL);
server_err->has_xml_response = TRUE;
+ server_err->contains_precondition_error = FALSE;
server_err->cdata = svn_stringbuf_create("", pool);
server_err->collect_cdata = FALSE;
server_err->parser.pool = server_err->error->pool;
@@ -945,6 +946,34 @@ svn_ra_serf__handle_status_only(serf_req
return svn_error_return(err);
}
+/* Given a string like "HTTP/1.1 500 (status)" in BUF, parse out the numeric
+ status code into *STATUS_CODE_OUT. Ignores leading whitespace. */
+static svn_error_t *
+parse_dav_status(int *status_code_out, svn_stringbuf_t *buf,
+ apr_pool_t *scratch_pool)
+{
+ svn_error_t *err;
+ const char *token;
+ char *tok_status;
+ svn_stringbuf_t *temp_buf = svn_stringbuf_dup(buf, scratch_pool);
+
+ svn_stringbuf_strip_whitespace(temp_buf);
+ token = apr_strtok(temp_buf->data, " \t\r\n", &tok_status);
+ if (token)
+ token = apr_strtok(NULL, " \t\r\n", &tok_status);
+ if (!token)
+ return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+ "Malformed DAV:status CDATA '%s'",
+ buf->data);
+ err = svn_cstring_atoi(status_code_out, token);
+ if (err)
+ return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, err,
+ "Malformed DAV:status CDATA '%s'",
+ buf->data);
+
+ return SVN_NO_ERROR;
+}
+
/*
* Expat callback invoked on a start element tag for a 207 response.
*/
@@ -968,6 +997,14 @@ start_207(svn_ra_serf__xml_parser_t *par
svn_stringbuf_setempty(ctx->cdata);
ctx->collect_cdata = TRUE;
}
+ else if (ctx->in_error &&
+ strcmp(name.namespace, "DAV:") == 0 &&
+ strcmp(name.name, "status") == 0)
+ {
+ /* Start collecting cdata. */
+ svn_stringbuf_setempty(ctx->cdata);
+ ctx->collect_cdata = TRUE;
+ }
return SVN_NO_ERROR;
}
@@ -993,7 +1030,22 @@ end_207(svn_ra_serf__xml_parser_t *parse
ctx->collect_cdata = FALSE;
ctx->error->message = apr_pstrmemdup(ctx->error->pool, ctx->cdata->data,
ctx->cdata->len);
- ctx->error->apr_err = SVN_ERR_RA_DAV_REQUEST_FAILED;
+ if (ctx->contains_precondition_error)
+ ctx->error->apr_err = SVN_ERR_FS_PROP_BASEVALUE_MISMATCH;
+ else
+ ctx->error->apr_err = SVN_ERR_RA_DAV_REQUEST_FAILED;
+ }
+ else if (ctx->in_error &&
+ strcmp(name.namespace, "DAV:") == 0 &&
+ strcmp(name.name, "status") == 0)
+ {
+ int status_code;
+
+ ctx->collect_cdata = FALSE;
+
+ SVN_ERR(parse_dav_status(&status_code, ctx->cdata, parser->pool));
+ if (status_code == 412)
+ ctx->contains_precondition_error = TRUE;
}
return SVN_NO_ERROR;
@@ -1044,6 +1096,7 @@ svn_ra_serf__handle_multistatus_only(ser
{
server_err->error = svn_error_create(APR_SUCCESS, NULL, NULL);
server_err->has_xml_response = TRUE;
+ server_err->contains_precondition_error = FALSE;
server_err->cdata = svn_stringbuf_create("", pool);
server_err->collect_cdata = FALSE;
server_err->parser.pool = server_err->error->pool;
@@ -1053,7 +1106,7 @@ svn_ra_serf__handle_multistatus_only(ser
server_err->parser.cdata = cdata_207;
server_err->parser.done = &ctx->done;
server_err->parser.ignore_errors = TRUE;
- }
+ }
else
{
ctx->done = TRUE;
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_svn/client.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_svn/client.c Tue Sep 28 17:35:22 2010
@@ -622,6 +622,7 @@ static svn_error_t *open_session(svn_ra_
/* In protocol version 2, we send back our protocol version, our
* capability list, and the URL, and subsequently there is an auth
* request. */
+ /* Client-side capabilities list: */
SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "n(wwwwww)cc(?c)",
(apr_uint64_t) 2,
SVN_RA_SVN_CAP_EDIT_PIPELINE,
@@ -813,16 +814,49 @@ static svn_error_t *ra_svn_get_dated_rev
return SVN_NO_ERROR;
}
+/* Forward declaration. */
+static svn_error_t *ra_svn_has_capability(svn_ra_session_t *session,
+ svn_boolean_t *has,
+ const char *capability,
+ apr_pool_t *pool);
+
static svn_error_t *ra_svn_change_rev_prop(svn_ra_session_t *session, svn_revnum_t rev,
const char *name,
+ const svn_string_t *const *old_value_p,
const svn_string_t *value,
apr_pool_t *pool)
{
svn_ra_svn__session_baton_t *sess_baton = session->priv;
svn_ra_svn_conn_t *conn = sess_baton->conn;
+ svn_boolean_t dont_care;
+ const svn_string_t *old_value;
+ svn_boolean_t has_atomic_revprops;
+
+ SVN_ERR(ra_svn_has_capability(session, &has_atomic_revprops,
+ SVN_RA_SVN_CAP_ATOMIC_REVPROPS,
+ pool));
+
+ if (old_value_p)
+ {
+ /* How did you get past the same check in svn_ra_change_rev_prop2()? */
+ SVN_ERR_ASSERT(has_atomic_revprops);
+
+ dont_care = FALSE;
+ old_value = *old_value_p;
+ }
+ else
+ {
+ dont_care = TRUE;
+ old_value = NULL;
+ }
+
+ if (has_atomic_revprops)
+ SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "change-rev-prop2", "rc(?s)(b?s)",
+ rev, name, value, dont_care, old_value));
+ else
+ SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "change-rev-prop", "rc?s",
+ rev, name, value));
- SVN_ERR(svn_ra_svn_write_cmd(conn, pool, "change-rev-prop", "rc?s",
- rev, name, value));
SVN_ERR(handle_auth_request(sess_baton, pool));
SVN_ERR(svn_ra_svn_read_cmd_response(conn, pool, ""));
return SVN_NO_ERROR;
@@ -2420,6 +2454,9 @@ static svn_error_t *ra_svn_has_capabilit
else if (strcmp(capability, SVN_RA_CAPABILITY_COMMIT_REVPROPS) == 0)
*has = svn_ra_svn_has_capability(sess->conn,
SVN_RA_SVN_CAP_COMMIT_REVPROPS);
+ else if (strcmp(capability, SVN_RA_CAPABILITY_ATOMIC_REVPROPS) == 0)
+ *has = svn_ra_svn_has_capability(sess->conn,
+ SVN_RA_SVN_CAP_ATOMIC_REVPROPS);
else /* Don't know any other capabilities, so error. */
{
return svn_error_createf
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_svn/editorp.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_svn/editorp.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_svn/editorp.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_svn/editorp.c Tue Sep 28 17:35:22 2010
@@ -904,7 +904,9 @@ svn_error_t *svn_ra_svn_drive_editor2(sv
svn_error_clear(editor->abort_edit(edit_baton, subpool));
svn_ra_svn__set_block_handler(conn, blocked_write, &state);
}
- write_err = svn_ra_svn_write_cmd_failure(conn, subpool, err->child);
+ write_err = svn_ra_svn_write_cmd_failure(
+ conn, subpool,
+ svn_ra_svn__locate_real_error_child(err));
if (!write_err)
write_err = svn_ra_svn_flush(conn, subpool);
svn_ra_svn__set_block_handler(conn, NULL, NULL);
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_svn/marshal.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_svn/marshal.c Tue Sep 28 17:35:22 2010
@@ -832,6 +832,21 @@ svn_error_t *svn_ra_svn_parse_proplist(c
/* --- READING AND WRITING COMMANDS AND RESPONSES --- */
+svn_error_t *svn_ra_svn__locate_real_error_child(svn_error_t *err)
+{
+ svn_error_t *this_link;
+
+ SVN_ERR_ASSERT(err);
+
+ for (this_link = err;
+ this_link && (this_link->apr_err == SVN_ERR_RA_SVN_CMD_ERR);
+ this_link = this_link->child)
+ ;
+
+ SVN_ERR_ASSERT(this_link);
+ return this_link;
+}
+
svn_error_t *svn_ra_svn__handle_failure_status(const apr_array_header_t *params,
apr_pool_t *pool)
{
@@ -860,12 +875,27 @@ svn_error_t *svn_ra_svn__handle_failure_
easily change that, so "" means a nonexistent message. */
if (!*message)
message = NULL;
- err = svn_error_create((apr_status_t)apr_err, err, message);
- err->file = apr_pstrdup(err->pool, file);
- err->line = (long)line;
+
+ /* Skip over links in the error chain that were intended only to
+ exist on the server (to wrap real errors intended for the
+ client) but accidentally got included in the server's actual
+ response. */
+ if ((apr_status_t)apr_err != SVN_ERR_RA_SVN_CMD_ERR)
+ {
+ err = svn_error_create((apr_status_t)apr_err, err, message);
+ err->file = apr_pstrdup(err->pool, file);
+ err->line = (long)line;
+ }
}
svn_pool_destroy(subpool);
+
+ /* If we get here, then we failed to find a real error in the error
+ chain that the server proported to be sending us. That's bad. */
+ if (! err)
+ err = svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,
+ _("Malformed error list"));
+
return err;
}
@@ -941,7 +971,9 @@ svn_error_t *svn_ra_svn_handle_commands2
if (err && err->apr_err == SVN_ERR_RA_SVN_CMD_ERR)
{
- write_err = svn_ra_svn_write_cmd_failure(conn, iterpool, err->child);
+ write_err = svn_ra_svn_write_cmd_failure(
+ conn, iterpool,
+ svn_ra_svn__locate_real_error_child(err));
svn_error_clear(err);
if (write_err)
return write_err;
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_svn/protocol
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_svn/protocol?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_svn/protocol (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_svn/protocol Tue Sep 28 17:35:22 2010
@@ -199,6 +199,9 @@ capability and C indicates a client capa
[S] depth If the server presents this capability, it understands
requested operational depth (see section 3.1.1) and
per-path ambient depth (see section 3.1.3).
+[S] atomic-revprops If the server presents this capability, it
+ supports the change-rev-prop2 command.
+ See section 3.1.1.
3. Commands
-----------
@@ -261,6 +264,16 @@ second place for auth-request point as n
changed to be optional without creating an optional tuple for
that one parameter as we normally do.)
+ change-rev-prop2
+ params: ( rev:number name:string [ value:string ]
+ ( dont-care:bool ? previous-value:string ) )
+ response: ( )
+ If value is not specified, the rev-prop is removed. If dont-care is false,
+ then the rev-prop is changed only if it is currently set as previous-value
+ indicates. (If dont-care is false and previous-value is unspecified, then
+ the revision property must be previously unset.) If dont-care is true,
+ then previous-value must not be specified.
+
rev-proplist
params: ( rev:number )
response: ( props:proplist )
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_svn/ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_svn/ra_svn.h?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_svn/ra_svn.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_svn/ra_svn.h Tue Sep 28 17:35:22 2010
@@ -122,6 +122,11 @@ svn_error_t *svn_ra_svn__cram_client(svn
const char *user, const char *password,
const char **message);
+/* Return a pointer to the error chain child of ERR which contains the
+ * first "real" error message, not merely one of the
+ * SVN_ERR_RA_SVN_CMD_ERR wrapper errors. */
+svn_error_t *svn_ra_svn__locate_real_error_child(svn_error_t *err);
+
/* Return an error chain based on @a params (which contains a
* command response indicating failure). The error chain will be
* in the same order as the errors indicated in @a params. Use
Modified: subversion/branches/javahl-ra/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_repos/deprecated.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_repos/deprecated.c Tue Sep 28 17:35:22 2010
@@ -328,6 +328,26 @@ svn_repos_replay(svn_fs_root_t *root,
/*** From fs-wrap.c ***/
svn_error_t *
+svn_repos_fs_change_rev_prop3(svn_repos_t *repos,
+ svn_revnum_t rev,
+ const char *author,
+ const char *name,
+ const svn_string_t *new_value,
+ svn_boolean_t use_pre_revprop_change_hook,
+ svn_boolean_t use_post_revprop_change_hook,
+ svn_repos_authz_func_t authz_read_func,
+ void *authz_read_baton,
+ apr_pool_t *pool)
+{
+ return svn_repos_fs_change_rev_prop4(repos, rev, author, name, NULL,
+ new_value,
+ use_pre_revprop_change_hook,
+ use_post_revprop_change_hook,
+ authz_read_func,
+ authz_read_baton, pool);
+}
+
+svn_error_t *
svn_repos_fs_change_rev_prop2(svn_repos_t *repos,
svn_revnum_t rev,
const char *author,
Modified: subversion/branches/javahl-ra/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_repos/fs-wrap.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_repos/fs-wrap.c Tue Sep 28 17:35:22 2010
@@ -263,10 +263,11 @@ svn_repos_fs_change_txn_prop(svn_fs_txn_
svn_error_t *
-svn_repos_fs_change_rev_prop3(svn_repos_t *repos,
+svn_repos_fs_change_rev_prop4(svn_repos_t *repos,
svn_revnum_t rev,
const char *author,
const char *name,
+ const svn_string_t *const *old_value_p,
const svn_string_t *new_value,
svn_boolean_t use_pre_revprop_change_hook,
svn_boolean_t use_post_revprop_change_hook,
@@ -274,7 +275,6 @@ svn_repos_fs_change_rev_prop3(svn_repos_
void *authz_read_baton,
apr_pool_t *pool)
{
- svn_string_t *old_value;
svn_repos_revision_access_level_t readability;
char action;
@@ -284,9 +284,26 @@ svn_repos_fs_change_rev_prop3(svn_repos_
if (readability == svn_repos_revision_access_full)
{
+ const svn_string_t *old_value;
+
SVN_ERR(validate_prop(name, new_value, pool));
- SVN_ERR(svn_fs_revision_prop(&old_value, repos->fs, rev, name, pool));
+ /* Fetch OLD_VALUE for svn_fs_change_rev_prop2(). */
+ if (old_value_p)
+ {
+ old_value = *old_value_p;
+ }
+ else
+ {
+ /* Get OLD_VALUE anyway, in order for ACTION and OLD_VALUE arguments
+ * to the hooks to be accurate. */
+ svn_string_t *old_value2;
+
+ SVN_ERR(svn_fs_revision_prop(&old_value2, repos->fs, rev, name, pool));
+ old_value = old_value2;
+ }
+
+ /* Prepare ACTION. */
if (! new_value)
action = 'D';
else if (! old_value)
@@ -294,12 +311,13 @@ svn_repos_fs_change_rev_prop3(svn_repos_
else
action = 'M';
+ /* ### currently not passing the old_value to hooks */
if (use_pre_revprop_change_hook)
SVN_ERR(svn_repos__hooks_pre_revprop_change(repos, rev, author, name,
new_value, action, pool));
- SVN_ERR(svn_fs_change_rev_prop2(repos->fs, rev, name, NULL,
- new_value, pool));
+ SVN_ERR(svn_fs_change_rev_prop2(repos->fs, rev, name,
+ &old_value, new_value, pool));
if (use_post_revprop_change_hook)
SVN_ERR(svn_repos__hooks_post_revprop_change(repos, rev, author, name,
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/error.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/error.c Tue Sep 28 17:35:22 2010
@@ -269,6 +269,18 @@ svn_error_root_cause(svn_error_t *err)
return err;
}
+svn_boolean_t
+svn_error_has_cause(svn_error_t *err, apr_status_t apr_err)
+{
+ svn_error_t *child;
+
+ for (child = err; child; child = child->child)
+ if (child->apr_err == apr_err)
+ return TRUE;
+
+ return FALSE;
+}
+
svn_error_t *
svn_error_dup(svn_error_t *err)
{
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/mergeinfo.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/mergeinfo.c Tue Sep 28 17:35:22 2010
@@ -1367,7 +1367,7 @@ svn_mergeinfo_catalog_merge(svn_mergeinf
change_elt = APR_ARRAY_IDX(sorted_changes, j, svn_sort__item_t);
res = svn_sort_compare_items_as_paths(&cat_elt, &change_elt);
- if (res == 0) /* Both catalogs have mergeinfo for a give path. */
+ if (res == 0) /* Both catalogs have mergeinfo for a given path. */
{
svn_mergeinfo_t mergeinfo = cat_elt.value;
svn_mergeinfo_t changes_mergeinfo = change_elt.value;
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/sqlite.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/sqlite.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/sqlite.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/sqlite.c Tue Sep 28 17:35:22 2010
@@ -941,6 +941,11 @@ svn_sqlite__open(svn_sqlite__db_t **db,
SVN_ERR(exec_sql(*db, "PRAGMA foreign_keys=ON;"));
#endif
+ /* Store temporary tables in RAM instead of in temporary files, but don't
+ fail on this if this option is disabled in the sqlite compilation by
+ setting SQLITE_TEMP_STORE to 0 (always to disk) */
+ svn_error_clear(exec_sql(*db, "PRAGMA temp_store = MEMORY;"));
+
/* Validate the schema, upgrading if necessary. */
if (upgrade_sql != NULL)
SVN_ERR(check_format(*db, latest_schema, upgrade_sql, scratch_pool));
Modified: subversion/branches/javahl-ra/subversion/libsvn_subr/svn_string.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_subr/svn_string.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_subr/svn_string.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_subr/svn_string.c Tue Sep 28 17:35:22 2010
@@ -661,7 +661,7 @@ svn_cstring_strtoui64(apr_uint64_t *n, c
val < 0 || (apr_uint64_t)val < minval || (apr_uint64_t)val > maxval)
return svn_error_return(
svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
- _("Number '%s' is out of range '[%lu, %lu]'"),
+ _("Number '%s' is out of range '[%llu, %llu]'"),
str, minval, maxval));
*n = val;
return SVN_NO_ERROR;
@@ -705,7 +705,7 @@ svn_cstring_strtoi64(apr_int64_t *n, con
val < minval || val > maxval)
return svn_error_return(
svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
- _("Number '%s' is out of range '[%ld, %ld]'"),
+ _("Number '%s' is out of range '[%lld, %lld]'"),
str, minval, maxval));
*n = val;
return SVN_NO_ERROR;
Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/adm_crawler.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/adm_crawler.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/adm_crawler.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/adm_crawler.c Tue Sep 28 17:35:22 2010
@@ -748,52 +748,21 @@ svn_wc_crawl_revisions5(svn_wc_context_t
db, local_abspath, scratch_pool,
scratch_pool);
- {
- svn_boolean_t has_base = TRUE;
+ if (err)
+ {
+ if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+ return svn_error_return(err);
- if (err)
- {
- if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
- return svn_error_return(err);
+ svn_error_clear(err);
+ SVN_ERR(svn_wc__db_read_kind(&target_kind, db, local_abspath, TRUE,
+ scratch_pool));
- svn_error_clear(err);
- has_base = FALSE;
- SVN_ERR(svn_wc__db_read_kind(&target_kind, db, local_abspath, TRUE,
- scratch_pool));
-
- if (target_kind == svn_wc__db_kind_file
- || target_kind == svn_wc__db_kind_symlink)
- status = svn_wc__db_status_absent; /* Crawl via parent dir */
- else
- status = svn_wc__db_status_not_present; /* As checkout */
- }
-
- /* ### Check the parentstub if we don't find a BASE. But don't
- do this if we already have the info we want or we break
- some copy scenarios. */
- if (!has_base && target_kind == svn_wc__db_kind_dir)
- {
- svn_boolean_t not_present;
- svn_revnum_t rev = SVN_INVALID_REVNUM;
- err = svn_wc__db_temp_is_dir_deleted(¬_present, &rev,
- db, local_abspath, scratch_pool);
-
- if (err && (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND
- || err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY))
- {
- svn_error_clear(err);
- not_present = FALSE;
- }
- else
- SVN_ERR(err);
-
- if (not_present)
- status = svn_wc__db_status_not_present;
-
- if (!SVN_IS_VALID_REVNUM(target_rev))
- target_rev = rev;
- }
- }
+ if (target_kind == svn_wc__db_kind_file
+ || target_kind == svn_wc__db_kind_symlink)
+ status = svn_wc__db_status_absent; /* Crawl via parent dir */
+ else
+ status = svn_wc__db_status_not_present; /* As checkout */
+ }
if ((status == svn_wc__db_status_not_present)
|| (target_kind == svn_wc__db_kind_dir
Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/adm_ops.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/adm_ops.c Tue Sep 28 17:35:22 2010
@@ -1288,12 +1288,11 @@ revert_entry(svn_depth_t *depth,
sure we leave a not-present node behind */
if (was_not_present)
{
- SVN_ERR(svn_wc__db_base_add_absent_node(
+ SVN_ERR(svn_wc__db_base_add_not_present_node(
db, local_abspath,
repos_relpath, repos_root_url, repos_uuid,
base_revision,
base_kind,
- svn_wc__db_status_not_present,
NULL, NULL,
pool));
}
Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/copy.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/copy.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/copy.c Tue Sep 28 17:35:22 2010
@@ -46,7 +46,8 @@
/*** Code. ***/
-/* Make a copy of SRC_ABSPATH under a temporary name in the directory
+/* Make a copy of the filesystem node (or tree if RECURSIVE) at
+ SRC_ABSPATH under a temporary name in the directory
TMPDIR_ABSPATH and return the absolute path of the copy in
*DST_ABSPATH. Return the node kind of SRC_ABSPATH in *KIND. If
SRC_ABSPATH doesn't exist then set *DST_ABSPATH to NULL to indicate
@@ -88,6 +89,10 @@ copy_to_tmpdir(const char **dst_abspath,
### handle the directory case and b) we need to be able to remove
### the cleanup before queueing the move work item. */
+ /* Set DST_ABSPATH to a temporary unique path. If *KIND is file, leave a
+ file there and then overwrite it; otherwise leave no node on disk at
+ that path. In the latter case, something else might use that path
+ before we get around to using it a moment later, but never mind. */
SVN_ERR(svn_io_open_unique_file3(NULL, dst_abspath, tmpdir_abspath,
delete_when, scratch_pool, scratch_pool));
@@ -115,10 +120,87 @@ copy_to_tmpdir(const char **dst_abspath,
}
-/* A replacement for both copy_file_administratively and
- copy_added_file_administratively. Not yet fully working. Relies
- on in-db-props. SRC_ABSPATH is a versioned file but the filesystem
- node might not be a file.
+/* If SRC_ABSPATH and DST_ABSPATH use different pristine stores, copy the
+ pristine text of SRC_ABSPATH (if there is one) into the pristine text
+ store connected to DST_ABSPATH. This will only happen when copying into
+ a separate WC such as an external directory.
+ */
+static svn_error_t *
+copy_pristine_text_if_necessary(svn_wc__db_t *db,
+ const char *src_abspath,
+ const char *dst_abspath,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ const svn_checksum_t *checksum;
+
+ SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ &checksum,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL,
+ db, src_abspath,
+ scratch_pool, scratch_pool));
+ if (checksum)
+ {
+ svn_boolean_t present;
+ svn_stream_t *src_pristine, *tmp_pristine;
+ const char *tmp_pristine_abspath;
+ const svn_checksum_t *sha1_checksum, *md5_checksum;
+ const char *tmpdir_abspath;
+
+ /* If it's already in DST_ABSPATH's pristine store, we're done. */
+ SVN_ERR(svn_wc__db_pristine_check(&present, db, dst_abspath, checksum,
+ scratch_pool));
+ if (present)
+ return SVN_NO_ERROR;
+
+ if (checksum->kind == svn_checksum_md5)
+ {
+ md5_checksum = checksum;
+ SVN_ERR(svn_wc__db_pristine_get_sha1(&sha1_checksum, db,
+ src_abspath, checksum,
+ scratch_pool, scratch_pool));
+ }
+ else
+ {
+ sha1_checksum = checksum;
+ SVN_ERR(svn_wc__db_pristine_get_md5(&md5_checksum, db,
+ src_abspath, checksum,
+ scratch_pool, scratch_pool));
+ }
+
+ SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&tmpdir_abspath, db, dst_abspath,
+ scratch_pool, scratch_pool));
+
+ SVN_ERR(svn_wc__db_pristine_read(&src_pristine, db,
+ src_abspath, sha1_checksum,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_stream_open_unique(&tmp_pristine, &tmp_pristine_abspath,
+ tmpdir_abspath, svn_io_file_del_none,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_stream_copy3(src_pristine, tmp_pristine,
+ cancel_func, cancel_baton,
+ scratch_pool));
+ SVN_ERR(svn_wc__db_pristine_install(db, tmp_pristine_abspath,
+ sha1_checksum, md5_checksum,
+ scratch_pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+/* Copy the versioned file SRC_ABSPATH in DB to the path DST_ABSPATH in DB.
+ If METADATA_ONLY is true, copy only the versioned metadata,
+ otherwise copy both the versioned metadata and the filesystem node (even
+ if it is the wrong kind, and recursively if it is a dir).
+
+ A replacement for both copy_file_administratively and
+ copy_added_file_administratively.
+
+ ### Not yet fully working. Relies on in-db-props.
This also works for versioned symlinks that are stored in the db as
svn_wc__db_kind_file with svn:special set. */
@@ -136,62 +218,20 @@ copy_versioned_file(svn_wc__db_t *db,
svn_skel_t *work_items = NULL;
const char *dir_abspath = svn_dirent_dirname(dst_abspath, scratch_pool);
const char *tmpdir_abspath;
- svn_stream_t *src_pristine;
const char *tmp_dst_abspath;
svn_node_kind_t kind;
SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&tmpdir_abspath, db, dst_abspath,
scratch_pool, scratch_pool));
- /* This goes away when we centralise, but until then we might need
- to do a cross-db pristine copy. */
- if (strcmp(svn_dirent_dirname(src_abspath, scratch_pool),
- svn_dirent_dirname(dst_abspath, scratch_pool)))
- {
- const svn_checksum_t *checksum;
-
- SVN_ERR(svn_wc__db_read_info(NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- &checksum,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- db, src_abspath,
- scratch_pool, scratch_pool));
- if (checksum)
- {
- svn_stream_t *tmp_pristine;
- const char *tmp_pristine_abspath;
- const svn_checksum_t *sha1_checksum, *md5_checksum;
-
- if (checksum->kind == svn_checksum_md5)
- {
- md5_checksum = checksum;
- SVN_ERR(svn_wc__db_pristine_get_sha1(&sha1_checksum, db,
- src_abspath, checksum,
- scratch_pool, scratch_pool));
- }
- else
- {
- sha1_checksum = checksum;
- SVN_ERR(svn_wc__db_pristine_get_md5(&md5_checksum, db,
- src_abspath, checksum,
- scratch_pool, scratch_pool));
- }
- SVN_ERR(svn_wc__db_pristine_read(&src_pristine, db,
- src_abspath, sha1_checksum,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_stream_open_unique(&tmp_pristine, &tmp_pristine_abspath,
- tmpdir_abspath, svn_io_file_del_none,
- scratch_pool, scratch_pool));
- SVN_ERR(svn_stream_copy3(src_pristine, tmp_pristine,
- cancel_func, cancel_baton,
- scratch_pool));
- SVN_ERR(svn_wc__db_pristine_install(db, tmp_pristine_abspath,
- sha1_checksum, md5_checksum,
- scratch_pool));
- }
- }
+ /* In case we are copying from one WC to another (e.g. an external dir),
+ ensure the destination WC has a copy of the pristine text. */
+ SVN_ERR(copy_pristine_text_if_necessary(db, src_abspath, dst_abspath,
+ cancel_func, cancel_baton,
+ scratch_pool));
+ /* Prepare a temp copy of the filesystem node. It is usually a file, but
+ copy recursively if it's a dir. */
if (!metadata_only)
{
SVN_ERR(copy_to_tmpdir(&tmp_dst_abspath, &kind, src_abspath,
@@ -209,6 +249,8 @@ copy_versioned_file(svn_wc__db_t *db,
}
}
+ /* Copy the (single) node's metadata, and move the new filesystem node
+ into place. */
SVN_ERR(svn_wc__db_op_copy(db, src_abspath, dst_abspath,
work_items, scratch_pool));
SVN_ERR(svn_wc__wq_run(db, dir_abspath,
@@ -225,6 +267,10 @@ copy_versioned_file(svn_wc__db_t *db,
return SVN_NO_ERROR;
}
+/* Copy the versioned dir SRC_ABSPATH in DB to the path DST_ABSPATH in DB,
+ recursively. If METADATA_ONLY is true, copy only the versioned metadata,
+ otherwise copy both the versioned metadata and the filesystem nodes (even
+ if they are the wrong kind, and including unversioned children). */
static svn_error_t *
copy_versioned_dir(svn_wc__db_t *db,
const char *src_abspath,
@@ -246,6 +292,7 @@ copy_versioned_dir(svn_wc__db_t *db,
apr_pool_t *iterpool;
int i;
+ /* Prepare a temp copy of the single filesystem node (usually a dir). */
if (!metadata_only)
{
SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&tmpdir_abspath, db,
@@ -266,6 +313,8 @@ copy_versioned_dir(svn_wc__db_t *db,
}
}
+ /* Copy the (single) node's metadata, and move the new filesystem node
+ into place. */
SVN_ERR(svn_wc__db_op_copy(db, src_abspath, dst_abspath,
work_items, scratch_pool));
SVN_ERR(svn_wc__wq_run(db, dir_abspath,
@@ -281,8 +330,8 @@ copy_versioned_dir(svn_wc__db_t *db,
}
if (!metadata_only && kind == svn_node_dir)
- /* All children, versioned and unversioned. We're only interested in the
- names of the children, so we can pass TRUE as the only_check_type
+ /* All filesystem children, versioned and unversioned. We're only
+ interested in their names, so we can pass TRUE as the only_check_type
param. */
SVN_ERR(svn_io_get_dirents3(&children, src_abspath, TRUE,
scratch_pool, scratch_pool));
@@ -330,9 +379,9 @@ copy_versioned_dir(svn_wc__db_t *db,
apr_hash_set(children, child_name, APR_HASH_KEY_STRING, NULL);
}
+ /* Copy all the remaining filesystem children, which are unversioned. */
if (!metadata_only && kind == svn_node_dir)
{
- /* All the remaining children are unversioned. */
apr_hash_index_t *hi;
for (hi = apr_hash_first(scratch_pool, children); hi;
@@ -392,7 +441,6 @@ svn_wc_copy3(svn_wc_context_t *wc_ctx,
apr_pool_t *scratch_pool)
{
svn_wc__db_t *db = wc_ctx->db;
- svn_node_kind_t src_kind;
svn_wc__db_kind_t src_db_kind;
const char *dstdir_abspath;
@@ -401,6 +449,8 @@ svn_wc_copy3(svn_wc_context_t *wc_ctx,
dstdir_abspath = svn_dirent_dirname(dst_abspath, scratch_pool);
+ /* Ensure DSTDIR_ABSPATH belongs to the same repository as SRC_ABSPATH;
+ throw an error if not. */
{
svn_wc__db_status_t src_status, dstdir_status;
const char *src_repos_root_url, *dst_repos_root_url;
@@ -481,6 +531,7 @@ svn_wc_copy3(svn_wc_context_t *wc_ctx,
SVN_ERR_WC_INVALID_SCHEDULE, NULL,
_("Cannot copy to '%s' as it is scheduled for deletion"),
svn_dirent_local_style(dst_abspath, scratch_pool));
+ /* ### should report dstdir_abspath instead of dst_abspath? */
}
/* TODO(#2843): Rework the error report. */
@@ -528,16 +579,13 @@ svn_wc_copy3(svn_wc_context_t *wc_ctx,
}
}
- SVN_ERR(svn_io_check_path(src_abspath, &src_kind, scratch_pool));
-
+ /* Check that the target path is not obstructed, if required. */
if (!metadata_only)
{
svn_node_kind_t dst_kind;
- /* This is the error checking from copy_file_administratively
- but converted to wc-ng. It's not in copy_file since this
- checking only needs to happen at the root of the copy and not
- when called recursively. */
+ /* (We need only to check the root of the copy, not every path inside
+ copy_versioned_file/_dir.) */
SVN_ERR(svn_io_check_path(dst_abspath, &dst_kind, scratch_pool));
if (dst_kind != svn_node_none)
return svn_error_createf(SVN_ERR_ENTRY_EXISTS, NULL,
Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/deprecated.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/deprecated.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/deprecated.c Tue Sep 28 17:35:22 2010
@@ -2945,7 +2945,6 @@ svn_wc_get_update_editor3(svn_revnum_t *
allow_unver_obstructions,
diff3_cmd,
preserved_exts,
- fetch_func, fetch_baton,
conflict_func, conflict_baton,
external_func, eb,
cancel_func, cancel_baton,
@@ -3062,7 +3061,6 @@ svn_wc_get_switch_editor3(svn_revnum_t *
allow_unver_obstructions,
diff3_cmd,
preserved_exts,
- NULL, NULL,
conflict_func, conflict_baton,
external_func, eb,
cancel_func, cancel_baton,
@@ -3366,12 +3364,16 @@ svn_wc_relocate3(const char *path,
const char *local_abspath;
svn_wc_context_t *wc_ctx;
+ if (! recurse)
+ svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, 0,
+ _("Non-recursive relocation not supported"));
+
SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
svn_wc__adm_get_db(adm_access),
pool));
- SVN_ERR(svn_wc_relocate4(wc_ctx, local_abspath, from, to, recurse,
+ SVN_ERR(svn_wc_relocate4(wc_ctx, local_abspath, from, to,
validator, validator_baton, pool));
return svn_error_return(svn_wc_context_destroy(wc_ctx));
Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/entries.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/entries.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/entries.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/entries.c Tue Sep 28 17:35:22 2010
@@ -606,16 +606,35 @@ read_one_entry(const svn_wc_entry_t **ne
{
svn_sqlite__db_t *sdb;
svn_sqlite__stmt_t *stmt;
+#ifdef SVN_WC__NODES
+ svn_sqlite__stmt_t *stmt_nodes;
+ svn_boolean_t have_nodes_row;
+#endif
SVN_ERR(svn_wc__db_temp_borrow_sdb(
&sdb, db, dir_abspath,
svn_wc__db_openmode_readonly,
scratch_pool));
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
STMT_SELECT_NOT_PRESENT));
SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, entry->name));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
+#endif
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__get_statement(&stmt_nodes, sdb,
+ STMT_SELECT_NOT_PRESENT));
+ SVN_ERR(svn_sqlite__bindf(stmt_nodes, "is", wc_id, entry->name));
+ SVN_ERR(svn_sqlite__step(&have_nodes_row, stmt_nodes));
+#ifndef SVN_WC__NODES_ONLY
+ SVN_ERR_ASSERT(have_row == have_nodes_row);
+ SVN_ERR(svn_sqlite__reset(stmt_nodes));
+#else
+ stmt = stmt_nodes;
+ have_row = have_nodes_row;
+#endif
+#endif
SVN_ERR(svn_sqlite__reset(stmt));
}
@@ -709,44 +728,16 @@ read_one_entry(const svn_wc_entry_t **ne
}
else
{
- /* If we are reading child directories, then we need to
- correctly populate the DELETED flag. WC_DB normally
- wants to provide all of a directory's metadata from
- its own area. But this information is stored only in
- the parent directory, so we need to call a custom API
- to fetch this value.
-
- ### we should start generating BASE_NODE rows for THIS_DIR
- ### in the subdir. future step because it is harder. */
- if (kind == svn_wc__db_kind_dir && *entry->name != '\0')
- {
- SVN_ERR(svn_wc__db_temp_is_dir_deleted(&entry->deleted,
- &entry->revision,
- db, entry_abspath,
- scratch_pool));
- }
- if (entry->deleted)
- {
- /* There was a DELETED marker in the parent, meaning
- that we truly are shadowing a base node. It isn't
- called a 'replace' though (the BASE is pretending
- not to exist). */
- entry->schedule = svn_wc_schedule_add;
- }
- else
- {
- /* There was NOT a 'not-present' BASE_NODE in the parent
- directory. And there is no BASE_NODE in this directory.
- Therefore, we are looking at some kind of add/copy
- rather than a replace. */
-
- /* ### if this looks like a plain old add, then rev=0. */
- if (!SVN_IS_VALID_REVNUM(entry->copyfrom_rev)
- && !SVN_IS_VALID_REVNUM(entry->cmt_rev))
- entry->revision = 0;
+ /* There is NO 'not-present' BASE_NODE for this node.
+ Therefore, we are looking at some kind of add/copy
+ rather than a replace. */
+
+ /* ### if this looks like a plain old add, then rev=0. */
+ if (!SVN_IS_VALID_REVNUM(entry->copyfrom_rev)
+ && !SVN_IS_VALID_REVNUM(entry->cmt_rev))
+ entry->revision = 0;
- entry->schedule = svn_wc_schedule_add;
- }
+ entry->schedule = svn_wc_schedule_add;
}
/* If we don't have "real" data from the entry (obstruction),
@@ -1677,6 +1668,7 @@ insert_working_node(svn_sqlite__db_t *sd
{
svn_sqlite__stmt_t *stmt;
+#ifndef SVN_WC__NODES_ONLY
/* ### NODE_DATA when switching to NODE_DATA, replace the
query below with STMT_INSERT_WORKING_NODE_DATA_2
and adjust the parameters bound. Can't do that yet. */
@@ -1748,68 +1740,60 @@ insert_working_node(svn_sqlite__db_t *sd
/* Execute and reset the insert clause. */
SVN_ERR(svn_sqlite__insert(NULL, stmt));
+#endif
-#ifdef SVN_WC__NODE_DATA
-
- SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
- STMT_INSERT_WORKING_NODE_DATA_1));
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_NODE));
+ SVN_ERR(svn_sqlite__bindf(stmt, "isisnnnnsnrisnnni",
+ working_node->wc_id, working_node->local_relpath,
+ (working_node->parent_relpath == NULL
+ ? (apr_int64_t)1 : (apr_int64_t)2),
+ working_node->parent_relpath,
+ /* Setting depth for files? */
+ svn_depth_to_word(working_node->depth),
+ working_node->changed_rev,
+ working_node->changed_date,
+ working_node->changed_author,
+ working_node->last_mod_time));
- SVN_ERR(svn_sqlite__bind_int64(stmt, 1, working_node->wc_id));
- SVN_ERR(svn_sqlite__bind_text(stmt, 2, working_node->local_relpath));
- SVN_ERR(svn_sqlite__bind_int64(stmt, 3,
- (*working_node->local_relpath == '\0') ? 1 : 2));
- SVN_ERR(svn_sqlite__bind_text(stmt, 4, working_node->parent_relpath));
+ if (working_node->copyfrom_repos_path)
+ {
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 5,
+ working_node->copyfrom_repos_id));
+ SVN_ERR(svn_sqlite__bind_text(stmt, 6,
+ working_node->copyfrom_repos_path));
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 7, working_node->copyfrom_revnum));
+ }
- /* ### need rest of values */
if (working_node->presence == svn_wc__db_status_normal)
- SVN_ERR(svn_sqlite__bind_text(stmt, 5, "normal"));
+ SVN_ERR(svn_sqlite__bind_text(stmt, 8, "normal"));
else if (working_node->presence == svn_wc__db_status_not_present)
- SVN_ERR(svn_sqlite__bind_text(stmt, 5, "not-present"));
+ SVN_ERR(svn_sqlite__bind_text(stmt, 8, "not-present"));
else if (working_node->presence == svn_wc__db_status_base_deleted)
- SVN_ERR(svn_sqlite__bind_text(stmt, 5, "base-deleted"));
+ SVN_ERR(svn_sqlite__bind_text(stmt, 8, "base-deleted"));
else if (working_node->presence == svn_wc__db_status_incomplete)
- SVN_ERR(svn_sqlite__bind_text(stmt, 5, "incomplete"));
+ SVN_ERR(svn_sqlite__bind_text(stmt, 8, "incomplete"));
else if (working_node->presence == svn_wc__db_status_excluded)
- SVN_ERR(svn_sqlite__bind_text(stmt, 5, "excluded"));
+ SVN_ERR(svn_sqlite__bind_text(stmt, 8, "excluded"));
if (working_node->kind == svn_node_none)
- SVN_ERR(svn_sqlite__bind_text(stmt, 6, "unknown"));
+ SVN_ERR(svn_sqlite__bind_text(stmt, 10, "unknown"));
else
- SVN_ERR(svn_sqlite__bind_text(stmt, 6,
+ SVN_ERR(svn_sqlite__bind_text(stmt, 10,
svn_node_kind_to_word(working_node->kind)));
- if (working_node->copyfrom_repos_path)
- {
- SVN_ERR(svn_sqlite__bind_int64(stmt, 7,
- working_node->copyfrom_repos_id));
- SVN_ERR(svn_sqlite__bind_text(stmt, 8,
- working_node->copyfrom_repos_path));
- SVN_ERR(svn_sqlite__bind_int64(stmt, 9, working_node->copyfrom_revnum));
- }
-
- if (working_node->checksum)
- SVN_ERR(svn_sqlite__bind_checksum(stmt, 10, working_node->checksum,
+ if (working_node->kind == svn_node_file)
+ SVN_ERR(svn_sqlite__bind_checksum(stmt, 14, working_node->checksum,
scratch_pool));
- if (SVN_IS_VALID_REVNUM(working_node->changed_rev))
- SVN_ERR(svn_sqlite__bind_int64(stmt, 11, working_node->changed_rev));
- if (working_node->changed_date)
- SVN_ERR(svn_sqlite__bind_int64(stmt, 12, working_node->changed_date));
- if (working_node->changed_author)
- SVN_ERR(svn_sqlite__bind_text(stmt, 13, working_node->changed_author));
-
- SVN_ERR(svn_sqlite__bind_text(stmt, 14,
- svn_depth_to_word(working_node->depth)));
-
if (working_node->properties)
SVN_ERR(svn_sqlite__bind_properties(stmt, 15, working_node->properties,
scratch_pool));
- /* ### we should bind 'symlink_target' (16) as appropriate. */
+ if (working_node->translated_size != SVN_INVALID_FILESIZE)
+ SVN_ERR(svn_sqlite__bind_int64(stmt, 16, working_node->translated_size));
- /* Execute and reset the insert clause. */
SVN_ERR(svn_sqlite__insert(NULL, stmt));
-
#endif
return SVN_NO_ERROR;
@@ -2173,6 +2157,7 @@ write_entry(svn_wc__db_t *db,
&entry->file_external_rev,
scratch_pool));
+#ifndef SVN_WC__NODES_ONLY
SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
STMT_UPDATE_FILE_EXTERNAL));
SVN_ERR(svn_sqlite__bindf(stmt, "iss",
@@ -2180,6 +2165,16 @@ write_entry(svn_wc__db_t *db,
entry->name,
str));
SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
+#ifdef SVN_WC__NODES
+ SVN_ERR(svn_sqlite__get_statement(&stmt, sdb,
+ STMT_UPDATE_FILE_EXTERNAL_1));
+ SVN_ERR(svn_sqlite__bindf(stmt, "iss",
+ (apr_uint64_t)1 /* wc_id */,
+ entry->name,
+ str));
+ SVN_ERR(svn_sqlite__step_done(stmt));
+#endif
}
}
Modified: subversion/branches/javahl-ra/subversion/libsvn_wc/relocate.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_wc/relocate.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_wc/relocate.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_wc/relocate.c Tue Sep 28 17:35:22 2010
@@ -76,7 +76,6 @@ svn_wc_relocate4(svn_wc_context_t *wc_ct
const char *local_abspath,
const char *from,
const char *to,
- svn_boolean_t recurse,
svn_wc_relocation_validator3_t validator,
void *validator_baton,
apr_pool_t *scratch_pool)
@@ -87,6 +86,35 @@ svn_wc_relocate4(svn_wc_context_t *wc_ct
const char *old_url;
const char *new_repos_root;
const char *uuid;
+ svn_boolean_t is_wc_root;
+
+ SVN_ERR(svn_wc__strictly_is_wc_root(&is_wc_root, wc_ctx, local_abspath,
+ scratch_pool));
+ if (! is_wc_root)
+ {
+ const char *wcroot_abspath;
+ svn_error_t *err;
+
+ err = svn_wc__db_get_wcroot(&wcroot_abspath, wc_ctx->db,
+ local_abspath, scratch_pool, scratch_pool);
+ if (err)
+ {
+ svn_error_clear(err);
+ return svn_error_createf(
+ SVN_ERR_WC_INVALID_OP_ON_CWD, NULL,
+ _("Cannot relocate '%s' as it is not the root of a working copy"),
+ svn_dirent_local_style(local_abspath, scratch_pool));
+ }
+ else
+ {
+ return svn_error_createf(
+ SVN_ERR_WC_INVALID_OP_ON_CWD, NULL,
+ _("Cannot relocate '%s' as it is not the root of a working copy; "
+ "try relocating '%s' instead"),
+ svn_dirent_local_style(local_abspath, scratch_pool),
+ svn_dirent_local_style(wcroot_abspath, scratch_pool));
+ }
+ }
SVN_ERR(svn_wc__db_read_info(NULL, &kind, NULL, &repos_relpath,
&old_repos_root, &uuid,
@@ -112,48 +140,7 @@ svn_wc_relocate4(svn_wc_context_t *wc_ct
SVN_ERR(validator(validator_baton, uuid, to, new_repos_root, scratch_pool));
- /* ### FIXME: This will ultimately cause the DAV cache to be
- recursively cleared, which is great in the recursive case, but
- overreaching otherwise. Granted, this only affects performance,
- and that only for DAV RA implementations that rely on the DAV
- cache. */
- SVN_ERR(svn_wc__db_global_relocate(wc_ctx->db, local_abspath, new_repos_root,
- scratch_pool));
-
- if (!recurse)
- {
- /* This gets sticky. We need to do the above relocation, and then
- relocate each of the children *back* to the original location. Ugh.
- */
- const apr_array_header_t *children;
- apr_pool_t *iterpool;
- int i;
-
- SVN_ERR(svn_wc__db_read_children(&children, wc_ctx->db, local_abspath,
- scratch_pool, scratch_pool));
- iterpool = svn_pool_create(scratch_pool);
- for (i = 0; i < children->nelts; i++)
- {
- const char *child = APR_ARRAY_IDX(children, i, const char *);
- const char *child_abspath;
- const char *child_from;
- const char *child_to;
-
- svn_pool_clear(iterpool);
- child_abspath = svn_dirent_join(local_abspath, child, iterpool);
-
- /* We invert the "from" and "to" because we're switching the
- children back to the original location. */
- child_from = svn_uri_join(to, child, iterpool);
- child_to = svn_uri_join(from, child, iterpool);
-
- SVN_ERR(svn_wc_relocate4(wc_ctx, child_abspath, child_from,
- child_to, TRUE, validator, validator_baton,
- iterpool));
- }
-
- svn_pool_destroy(iterpool);
- }
-
- return SVN_NO_ERROR;
+ return svn_error_return(svn_wc__db_global_relocate(wc_ctx->db, local_abspath,
+ new_repos_root,
+ scratch_pool));
}