Alien-SVN
view release on metacpan or search on metacpan
src/subversion/subversion/libsvn_ra_serf/commit.c view on Meta::CPAN
/* Is this file being added? (Otherwise, just opened.) */
svn_boolean_t added;
dir_context_t *parent_dir;
const char *relpath;
const char *name;
/* The checked-out working resource for this file. */
const char *working_url;
/* The base revision of the file. */
svn_revnum_t base_revision;
/* Copy path and revision */
const char *copy_path;
svn_revnum_t copy_revision;
/* stream */
svn_stream_t *stream;
/* Temporary file containing the svndiff. */
apr_file_t *svndiff;
/* Our base checksum as reported by the WC. */
const char *base_checksum;
/* Our resulting checksum as reported by the WC. */
const char *result_checksum;
/* Changed and removed properties. */
apr_hash_t *changed_props;
apr_hash_t *removed_props;
/* URL to PUT the file at. */
const char *url;
} file_context_t;
/* Setup routines and handlers for various requests we'll invoke. */
static svn_error_t *
return_response_err(svn_ra_serf__handler_t *handler)
{
svn_error_t *err;
/* We should have captured SLINE and LOCATION in the HANDLER. */
SVN_ERR_ASSERT(handler->handler_pool != NULL);
/* Ye Olde Fallback Error */
err = svn_error_compose_create(
handler->server_error != NULL
? handler->server_error->error
: SVN_NO_ERROR,
svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
_("%s of '%s': %d %s"),
handler->method, handler->path,
handler->sline.code, handler->sline.reason));
/* Try to return one of the standard errors for 301, 404, etc.,
then look for an error embedded in the response. */
return svn_error_compose_create(svn_ra_serf__error_on_status(
handler->sline,
handler->path,
handler->location),
err);
}
/* Implements svn_ra_serf__request_body_delegate_t */
static svn_error_t *
create_checkout_body(serf_bucket_t **bkt,
void *baton,
serf_bucket_alloc_t *alloc,
apr_pool_t *pool)
{
const char *activity_url = baton;
serf_bucket_t *body_bkt;
body_bkt = serf_bucket_aggregate_create(alloc);
svn_ra_serf__add_xml_header_buckets(body_bkt, alloc);
svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:checkout",
"xmlns:D", "DAV:",
NULL);
svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:activity-set", NULL);
svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "D:href", NULL);
SVN_ERR_ASSERT(activity_url != NULL);
svn_ra_serf__add_cdata_len_buckets(body_bkt, alloc,
activity_url,
strlen(activity_url));
svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:href");
svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:activity-set");
svn_ra_serf__add_tag_buckets(body_bkt, "D:apply-to-version", NULL, alloc);
svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "D:checkout");
*bkt = body_bkt;
return SVN_NO_ERROR;
}
/* Using the HTTPv1 protocol, perform a CHECKOUT of NODE_URL within the
given COMMIT_CTX. The resulting working resource will be returned in
*WORKING_URL, allocated from RESULT_POOL. All temporary allocations
are performed in SCRATCH_POOL.
### are these URLs actually repos relpath values? or fspath? or maybe
### the abspath portion of the full URL.
This function operates synchronously.
Strictly speaking, we could perform "all" of the CHECKOUT requests
when the commit starts, and only block when we need a specific
answer. Or, at a minimum, send off these individual requests async
and block when we need the answer (eg PUT or PROPPATCH).
However: the investment to speed this up is not worthwhile, given
that CHECKOUT (and the related round trip) is completely obviated
in HTTPv2.
src/subversion/subversion/libsvn_ra_serf/commit.c view on Meta::CPAN
prc->handler, scratch_pool);
}
/* Commit baton callbacks */
static svn_error_t *
open_root(void *edit_baton,
svn_revnum_t base_revision,
apr_pool_t *dir_pool,
void **root_baton)
{
commit_context_t *ctx = edit_baton;
svn_ra_serf__handler_t *handler;
proppatch_context_t *proppatch_ctx;
dir_context_t *dir;
apr_hash_index_t *hi;
const char *proppatch_target = NULL;
if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(ctx->session))
{
post_response_ctx_t *prc;
const char *rel_path;
svn_boolean_t post_with_revprops
= (NULL != svn_hash_gets(ctx->session->supported_posts,
"create-txn-with-props"));
/* Create our activity URL now on the server. */
handler = apr_pcalloc(ctx->pool, sizeof(*handler));
handler->handler_pool = ctx->pool;
handler->method = "POST";
handler->body_type = SVN_SKEL_MIME_TYPE;
handler->body_delegate = create_txn_post_body;
handler->body_delegate_baton =
post_with_revprops ? ctx->revprop_table : NULL;
handler->header_delegate = setup_post_headers;
handler->header_delegate_baton = NULL;
handler->path = ctx->session->me_resource;
handler->conn = ctx->session->conns[0];
handler->session = ctx->session;
prc = apr_pcalloc(ctx->pool, sizeof(*prc));
prc->handler = handler;
prc->commit_ctx = ctx;
handler->response_handler = post_response_handler;
handler->response_baton = prc;
SVN_ERR(svn_ra_serf__context_run_one(handler, ctx->pool));
if (handler->sline.code != 201)
{
apr_status_t status = SVN_ERR_RA_DAV_REQUEST_FAILED;
switch (handler->sline.code)
{
case 403:
status = SVN_ERR_RA_DAV_FORBIDDEN;
break;
case 404:
status = SVN_ERR_FS_NOT_FOUND;
break;
}
return svn_error_createf(status, NULL,
_("%s of '%s': %d %s (%s://%s)"),
handler->method, handler->path,
handler->sline.code, handler->sline.reason,
ctx->session->session_url.scheme,
ctx->session->session_url.hostinfo);
}
if (! (ctx->txn_root_url && ctx->txn_url))
{
return svn_error_createf(
SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
_("POST request did not return transaction information"));
}
/* Fixup the txn_root_url to point to the anchor of the commit. */
SVN_ERR(svn_ra_serf__get_relative_path(&rel_path,
ctx->session->session_url.path,
ctx->session, NULL, dir_pool));
ctx->txn_root_url = svn_path_url_add_component2(ctx->txn_root_url,
rel_path, ctx->pool);
/* Build our directory baton. */
dir = apr_pcalloc(dir_pool, sizeof(*dir));
dir->pool = dir_pool;
dir->commit = ctx;
dir->base_revision = base_revision;
dir->relpath = "";
dir->name = "";
dir->changed_props = apr_hash_make(dir->pool);
dir->removed_props = apr_hash_make(dir->pool);
dir->url = apr_pstrdup(dir->pool, ctx->txn_root_url);
/* If we included our revprops in the POST, we need not
PROPPATCH them. */
proppatch_target = post_with_revprops ? NULL : ctx->txn_url;
}
else
{
const char *activity_str = ctx->session->activity_collection_url;
if (!activity_str)
SVN_ERR(svn_ra_serf__v1_get_activity_collection(&activity_str,
ctx->session->conns[0],
ctx->pool,
ctx->pool));
/* Cache the result. */
if (activity_str)
{
ctx->session->activity_collection_url =
apr_pstrdup(ctx->session->pool, activity_str);
}
else
{
return svn_error_create(SVN_ERR_RA_DAV_OPTIONS_REQ_FAILED, NULL,
_("The OPTIONS response did not include the "
"requested activity-collection-set value"));
}
ctx->activity_url =
svn_path_url_add_component2(activity_str, svn_uuid_generate(ctx->pool),
ctx->pool);
/* Create our activity URL now on the server. */
handler = apr_pcalloc(ctx->pool, sizeof(*handler));
handler->handler_pool = ctx->pool;
handler->method = "MKACTIVITY";
handler->path = ctx->activity_url;
handler->conn = ctx->session->conns[0];
handler->session = ctx->session;
handler->response_handler = svn_ra_serf__expect_empty_body;
handler->response_baton = handler;
SVN_ERR(svn_ra_serf__context_run_one(handler, ctx->pool));
if (handler->sline.code != 201)
{
apr_status_t status = SVN_ERR_RA_DAV_REQUEST_FAILED;
switch (handler->sline.code)
{
case 403:
status = SVN_ERR_RA_DAV_FORBIDDEN;
break;
case 404:
status = SVN_ERR_FS_NOT_FOUND;
break;
}
return svn_error_createf(status, NULL,
_("%s of '%s': %d %s (%s://%s)"),
handler->method, handler->path,
handler->sline.code, handler->sline.reason,
ctx->session->session_url.scheme,
ctx->session->session_url.hostinfo);
}
/* Now go fetch our VCC and baseline so we can do a CHECKOUT. */
SVN_ERR(svn_ra_serf__discover_vcc(&(ctx->vcc_url), ctx->session,
ctx->conn, ctx->pool));
/* Build our directory baton. */
dir = apr_pcalloc(dir_pool, sizeof(*dir));
dir->pool = dir_pool;
dir->commit = ctx;
dir->base_revision = base_revision;
dir->relpath = "";
dir->name = "";
dir->changed_props = apr_hash_make(dir->pool);
dir->removed_props = apr_hash_make(dir->pool);
SVN_ERR(get_version_url(&dir->url, dir->commit->session,
dir->relpath,
dir->base_revision, ctx->checked_in_url,
dir->pool, dir->pool /* scratch_pool */));
ctx->checked_in_url = dir->url;
/* Checkout our root dir */
SVN_ERR(checkout_dir(dir, dir->pool /* scratch_pool */));
proppatch_target = ctx->baseline_url;
}
/* Unless this is NULL -- which means we don't need to PROPPATCH the
transaction with our revprops -- then, you know, PROPPATCH the
transaction with our revprops. */
if (proppatch_target)
{
proppatch_ctx = apr_pcalloc(ctx->pool, sizeof(*proppatch_ctx));
proppatch_ctx->pool = dir_pool;
proppatch_ctx->commit = ctx;
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);
proppatch_ctx->base_revision = SVN_INVALID_REVNUM;
for (hi = apr_hash_first(ctx->pool, ctx->revprop_table); hi;
hi = apr_hash_next(hi))
{
const char *name = svn__apr_hash_index_key(hi);
svn_string_t *value = svn__apr_hash_index_val(hi);
const char *ns;
if (strncmp(name, SVN_PROP_PREFIX, sizeof(SVN_PROP_PREFIX) - 1) == 0)
src/subversion/subversion/libsvn_ra_serf/commit.c view on Meta::CPAN
new_file->pool = file_pool;
dir->ref_count++;
new_file->parent_dir = dir;
new_file->commit = dir->commit;
new_file->relpath = apr_pstrdup(new_file->pool, path);
new_file->name = svn_relpath_basename(new_file->relpath, NULL);
new_file->added = TRUE;
new_file->base_revision = SVN_INVALID_REVNUM;
new_file->copy_path = apr_pstrdup(new_file->pool, copy_path);
new_file->copy_revision = copy_revision;
new_file->changed_props = apr_hash_make(new_file->pool);
new_file->removed_props = apr_hash_make(new_file->pool);
/* Ensure that the file doesn't exist by doing a HEAD on the
resource. If we're using HTTP v2, we'll just look into the
transaction root tree for this thing. */
if (USING_HTTPV2_COMMIT_SUPPORT(dir->commit))
{
new_file->url = svn_path_url_add_component2(dir->commit->txn_root_url,
path, new_file->pool);
}
else
{
/* Ensure our parent directory has been checked out */
SVN_ERR(checkout_dir(dir, new_file->pool /* scratch_pool */));
new_file->url =
svn_path_url_add_component2(dir->working_url,
new_file->name, new_file->pool);
}
while (deleted_parent && deleted_parent[0] != '\0')
{
if (svn_hash_gets(dir->commit->deleted_entries, deleted_parent))
{
break;
}
deleted_parent = svn_relpath_dirname(deleted_parent, file_pool);
}
if (! ((dir->added && !dir->copy_path) ||
(deleted_parent && deleted_parent[0] != '\0')))
{
svn_ra_serf__handler_t *handler;
handler = apr_pcalloc(new_file->pool, sizeof(*handler));
handler->handler_pool = new_file->pool;
handler->session = new_file->commit->session;
handler->conn = new_file->commit->conn;
handler->method = "HEAD";
handler->path = svn_path_url_add_component2(
dir->commit->session->session_url.path,
path, new_file->pool);
handler->response_handler = svn_ra_serf__expect_empty_body;
handler->response_baton = handler;
SVN_ERR(svn_ra_serf__context_run_one(handler, new_file->pool));
if (handler->sline.code != 404)
{
if (handler->sline.code != 200)
{
svn_error_t *err;
err = svn_ra_serf__error_on_status(handler->sline,
handler->path,
handler->location);
SVN_ERR(err);
}
return svn_error_createf(SVN_ERR_FS_ALREADY_EXISTS, NULL,
_("File '%s' already exists"), path);
}
}
*file_baton = new_file;
return SVN_NO_ERROR;
}
static svn_error_t *
open_file(const char *path,
void *parent_baton,
svn_revnum_t base_revision,
apr_pool_t *file_pool,
void **file_baton)
{
dir_context_t *parent = parent_baton;
file_context_t *new_file;
new_file = apr_pcalloc(file_pool, sizeof(*new_file));
new_file->pool = file_pool;
parent->ref_count++;
new_file->parent_dir = parent;
new_file->commit = parent->commit;
new_file->relpath = apr_pstrdup(new_file->pool, path);
new_file->name = svn_relpath_basename(new_file->relpath, NULL);
new_file->added = FALSE;
new_file->base_revision = base_revision;
new_file->changed_props = apr_hash_make(new_file->pool);
new_file->removed_props = apr_hash_make(new_file->pool);
if (USING_HTTPV2_COMMIT_SUPPORT(parent->commit))
{
new_file->url = svn_path_url_add_component2(parent->commit->txn_root_url,
path, new_file->pool);
}
else
{
/* CHECKOUT the file into our activity. */
SVN_ERR(checkout_file(new_file, new_file->pool /* scratch_pool */));
new_file->url = new_file->working_url;
}
*file_baton = new_file;
src/subversion/subversion/libsvn_ra_serf/commit.c view on Meta::CPAN
SVN_ERR(ctx->callback(commit_info, ctx->callback_baton, pool));
/* If we're using activities, DELETE our completed activity. */
if (ctx->activity_url)
{
svn_ra_serf__handler_t *handler;
handler = apr_pcalloc(pool, sizeof(*handler));
handler->handler_pool = pool;
handler->method = "DELETE";
handler->path = ctx->activity_url;
handler->conn = ctx->conn;
handler->session = ctx->session;
handler->response_handler = svn_ra_serf__expect_empty_body;
handler->response_baton = handler;
SVN_ERR(svn_ra_serf__context_run_one(handler, pool));
SVN_ERR_ASSERT(handler->sline.code == 204);
}
return SVN_NO_ERROR;
}
static svn_error_t *
abort_edit(void *edit_baton,
apr_pool_t *pool)
{
commit_context_t *ctx = edit_baton;
svn_ra_serf__handler_t *handler;
/* If an activity or transaction wasn't even created, don't bother
trying to delete it. */
if (! (ctx->activity_url || ctx->txn_url))
return SVN_NO_ERROR;
/* An error occurred on conns[0]. serf 0.4.0 remembers that the connection
had a problem. We need to reset it, in order to use it again. */
serf_connection_reset(ctx->session->conns[0]->conn);
/* DELETE our aborted activity */
handler = apr_pcalloc(pool, sizeof(*handler));
handler->handler_pool = pool;
handler->method = "DELETE";
handler->conn = ctx->session->conns[0];
handler->session = ctx->session;
handler->response_handler = svn_ra_serf__expect_empty_body;
handler->response_baton = handler;
if (USING_HTTPV2_COMMIT_SUPPORT(ctx)) /* HTTP v2 */
handler->path = ctx->txn_url;
else
handler->path = ctx->activity_url;
SVN_ERR(svn_ra_serf__context_run_one(handler, pool));
/* 204 if deleted,
403 if DELETE was forbidden (indicates MKACTIVITY was forbidden too),
404 if the activity wasn't found. */
if (handler->sline.code != 204
&& handler->sline.code != 403
&& handler->sline.code != 404
)
{
return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
_("DELETE returned unexpected status: %d"),
handler->sline.code);
}
return SVN_NO_ERROR;
}
svn_error_t *
svn_ra_serf__get_commit_editor(svn_ra_session_t *ra_session,
const svn_delta_editor_t **ret_editor,
void **edit_baton,
apr_hash_t *revprop_table,
svn_commit_callback2_t callback,
void *callback_baton,
apr_hash_t *lock_tokens,
svn_boolean_t keep_locks,
apr_pool_t *pool)
{
svn_ra_serf__session_t *session = ra_session->priv;
svn_delta_editor_t *editor;
commit_context_t *ctx;
const char *repos_root;
const char *base_relpath;
svn_boolean_t supports_ephemeral_props;
ctx = apr_pcalloc(pool, sizeof(*ctx));
ctx->pool = pool;
ctx->session = session;
ctx->conn = session->conns[0];
ctx->revprop_table = svn_prop_hash_dup(revprop_table, pool);
/* If the server supports ephemeral properties, add some carrying
interesting version information. */
SVN_ERR(svn_ra_serf__has_capability(ra_session, &supports_ephemeral_props,
SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS,
pool));
if (supports_ephemeral_props)
{
svn_hash_sets(ctx->revprop_table,
apr_pstrdup(pool, SVN_PROP_TXN_CLIENT_COMPAT_VERSION),
svn_string_create(SVN_VER_NUMBER, pool));
svn_hash_sets(ctx->revprop_table,
apr_pstrdup(pool, SVN_PROP_TXN_USER_AGENT),
svn_string_create(session->useragent, pool));
}
ctx->callback = callback;
ctx->callback_baton = callback_baton;
ctx->lock_tokens = (lock_tokens && apr_hash_count(lock_tokens))
? lock_tokens : NULL;
ctx->keep_locks = keep_locks;
ctx->deleted_entries = apr_hash_make(ctx->pool);
( run in 0.541 second using v1.01-cache-2.11-cpan-39bf76dae61 )