summaryrefslogtreecommitdiff
path: root/subversion/libsvn_ra_neon/merge.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_ra_neon/merge.c')
-rw-r--r--subversion/libsvn_ra_neon/merge.c786
1 files changed, 0 insertions, 786 deletions
diff --git a/subversion/libsvn_ra_neon/merge.c b/subversion/libsvn_ra_neon/merge.c
deleted file mode 100644
index dc0647d..0000000
--- a/subversion/libsvn_ra_neon/merge.c
+++ /dev/null
@@ -1,786 +0,0 @@
-/*
- * merge.c : routines for performing a MERGE server requests
- *
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- * ====================================================================
- */
-
-
-
-#include <apr_pools.h>
-#include <apr_hash.h>
-#define APR_WANT_STRFUNC
-#include <apr_want.h>
-
-#include "svn_string.h"
-#include "svn_error.h"
-#include "svn_path.h"
-#include "svn_ra.h"
-#include "svn_pools.h"
-#include "svn_props.h"
-#include "svn_xml.h"
-
-#include "private/svn_dav_protocol.h"
-#include "private/svn_fspath.h"
-
-#include "svn_private_config.h"
-
-#include "ra_neon.h"
-
-
-static const svn_ra_neon__xml_elm_t merge_elements[] =
-{
- { "DAV:", "updated-set", ELEM_updated_set, 0 },
- { "DAV:", "merged-set", ELEM_merged_set, 0 },
- { "DAV:", "ignored-set", ELEM_ignored_set, 0 },
- { "DAV:", "href", ELEM_href, SVN_RA_NEON__XML_CDATA },
- { "DAV:", "merge-response", ELEM_merge_response, 0 },
- { "DAV:", "checked-in", ELEM_checked_in, 0 },
- { "DAV:", "response", ELEM_response, 0 },
- { "DAV:", "propstat", ELEM_propstat, 0 },
- { "DAV:", "status", ELEM_status, SVN_RA_NEON__XML_CDATA },
- { "DAV:", "responsedescription", ELEM_responsedescription,
- SVN_RA_NEON__XML_CDATA },
- { "DAV:", "prop", ELEM_prop, 0 },
- { "DAV:", "resourcetype", ELEM_resourcetype, 0 },
- { "DAV:", "collection", ELEM_collection, 0 },
- { "DAV:", "baseline", ELEM_baseline, 0 },
- { "DAV:", SVN_DAV__VERSION_NAME, ELEM_version_name, SVN_RA_NEON__XML_CDATA },
- { SVN_XML_NAMESPACE, "post-commit-err",
- ELEM_post_commit_err, SVN_RA_NEON__XML_CDATA },
- { "DAV:", SVN_DAV__CREATIONDATE, ELEM_creationdate, SVN_RA_NEON__XML_CDATA },
- { "DAV:", "creator-displayname", ELEM_creator_displayname,
- SVN_RA_NEON__XML_CDATA },
-
- { NULL }
-};
-
-enum merge_rtype {
- RTYPE_UNKNOWN, /* unknown (haven't seen it in the response yet) */
- RTYPE_REGULAR, /* a regular (member) resource */
- RTYPE_COLLECTION, /* a collection resource */
- RTYPE_BASELINE /* a baseline resource */
-};
-
-typedef struct merge_ctx_t {
- /*WARNING: WANT_CDATA should stay the first element in the baton:
- svn_ra_neon__xml_collect_cdata() assumes the baton starts with a stringbuf.
- */
- svn_stringbuf_t *want_cdata;
- svn_stringbuf_t *cdata;
- apr_pool_t *pool;
-
- /* a clearable subpool of pool, for loops. Do not use for anything
- that must persist beyond the scope of your function! */
- apr_pool_t *scratchpool;
-
- /* the BASE_HREF contains the merge target. as resources are specified in
- the merge response, we make their URLs relative to this URL, thus giving
- us a path for use in the commit callbacks. */
- const char *base_href;
-
- svn_revnum_t rev; /* the new/target revision number for this commit */
-
- svn_boolean_t response_has_error;
- int response_parent; /* what element did DAV:response appear within? */
-
- int href_parent; /* what element is the DAV:href appearing within? */
- svn_stringbuf_t *href; /* current response */
-
- int status; /* HTTP status for this DAV:propstat */
- enum merge_rtype rtype; /* DAV:resourcetype of this resource */
-
- svn_stringbuf_t *vsn_name; /* DAV:version-name for this resource */
- svn_stringbuf_t *vsn_url; /* DAV:checked-in for this resource */
- svn_stringbuf_t *committed_date; /* DAV:creationdate for this resource */
- svn_stringbuf_t *last_author; /* DAV:creator-displayname for this
- resource */
- svn_stringbuf_t *post_commit_err;/* SVN_XML_NAMESPACE:post-commit hook's
- stderr */
-
- /* We only invoke set_prop() on targets listed in valid_targets.
- Some entities (such as directories that have had changes
- committed underneath but are not themselves targets) will be
- mentioned in the merge response but not appear in
- valid_targets. */
- apr_hash_t *valid_targets;
-
- /* Client callbacks */
- svn_ra_push_wc_prop_func_t push_prop;
- void *cb_baton; /* baton for above */
-
-} merge_ctx_t;
-
-
-static void add_ignored(merge_ctx_t *mc, const char *cdata)
-{
- /* ### the server didn't check in the file(!) */
- /* ### remember the file and issue a report/warning later */
-}
-
-
-static svn_boolean_t okay_to_bump_path(const char *path,
- apr_hash_t *valid_targets,
- apr_pool_t *pool)
-{
- svn_stringbuf_t *parent_path;
- enum svn_recurse_kind r;
-
- /* Easy check: if path itself is in the hash, then it's legit. */
- if (apr_hash_get(valid_targets, path, APR_HASH_KEY_STRING))
- return TRUE;
- /* Otherwise, this path is bumpable IFF one of its parents is in the
- hash and marked with a 'recursion' flag. */
- parent_path = svn_stringbuf_create(path, pool);
-
- do {
- apr_size_t len = parent_path->len;
- svn_path_remove_component(parent_path);
- if (len == parent_path->len)
- break;
- r = (enum svn_recurse_kind) apr_hash_get(valid_targets,
- parent_path->data,
- APR_HASH_KEY_STRING);
- if (r == svn_recursive)
- return TRUE;
-
- } while (! svn_path_is_empty(parent_path->data));
-
- /* Default answer: if we get here, don't allow the bumping. */
- return FALSE;
-}
-
-
-/* If committed PATH appears in MC->valid_targets, and an MC->push_prop
- * function exists, then store VSN_URL as the SVN_RA_NEON__LP_VSN_URL
- * property on PATH. Use POOL for all allocations.
- *
- * Otherwise, just return SVN_NO_ERROR.
- */
-static svn_error_t *bump_resource(merge_ctx_t *mc,
- const char *path,
- char *vsn_url,
- apr_pool_t *pool)
-{
- /* no sense in doing any more work if there's no property setting
- function at our disposal. */
- if (mc->push_prop == NULL)
- return SVN_NO_ERROR;
-
- /* Only invoke a client callback on PATH if PATH counts as a
- committed target. The commit-tracking editor built this list for
- us, and took care not to include directories unless they were
- directly committed (i.e., received a property change). */
- if (! okay_to_bump_path(path, mc->valid_targets, pool))
- return SVN_NO_ERROR;
-
- /* Okay, NOW set the new version url. */
- {
- svn_string_t vsn_url_str; /* prop setter wants an svn_string_t */
-
- vsn_url_str.data = vsn_url;
- vsn_url_str.len = strlen(vsn_url);
-
- return (*mc->push_prop)(mc->cb_baton, path,
- SVN_RA_NEON__LP_VSN_URL, &vsn_url_str,
- pool);
- }
-}
-
-static svn_error_t * handle_resource(merge_ctx_t *mc,
- apr_pool_t *pool)
-{
- const char *relative;
-
- if (mc->response_has_error)
- {
- /* ### what to do? */
- /* ### return "no error", presuming whatever set response_has_error
- ### has already handled the problem. */
- return SVN_NO_ERROR;
- }
- if (mc->response_parent == ELEM_merged_set)
- {
- /* ### shouldn't have happened. we told the server "don't merge" */
- /* ### need something better than APR_EGENERAL */
- return svn_error_createf(APR_EGENERAL, NULL,
- _("Protocol error: we told the server not to "
- "auto-merge any resources, but it said that "
- "'%s' was merged"), mc->href->data);
- }
- if (mc->response_parent != ELEM_updated_set)
- {
- /* ### unknown parent for this response(!) */
- /* ### need something better than APR_EGENERAL */
- return svn_error_createf(APR_EGENERAL, NULL,
- _("Internal error: there is an unknown parent "
- "(%d) for the 'DAV:response' element within"
- " the MERGE response"), mc->response_parent);
- }
-#if 0
- /* ### right now, the server isn't sending everything for all resources.
- ### just skip this requirement. */
- if (mc->href->len == 0
- || mc->vsn_name->len == 0
- || mc->vsn_url->len == 0
- || mc->rtype == RTYPE_UNKNOWN)
- {
- /* one or more properties were missing in the DAV:response for the
- resource. */
- return svn_error_createf(APR_EGENERAL, NULL,
- _("Protocol error: the MERGE response for the "
- "'%s' resource did not return all of the "
- "properties that we asked for (and need to "
- "complete the commit)"), mc->href->data);
- }
-#endif
-
- if (mc->rtype == RTYPE_BASELINE)
- {
- /* cool. the DAV:version-name tells us the new revision */
- mc->rev = SVN_STR_TO_REV(mc->vsn_name->data);
- return SVN_NO_ERROR;
- }
-
- /* a collection or regular resource */
- if (! svn_urlpath__is_ancestor(mc->base_href, mc->href->data))
- {
- /* ### need something better than APR_EGENERAL */
- return svn_error_createf(APR_EGENERAL, NULL,
- _("A MERGE response for '%s' is not a child "
- "of the destination ('%s')"),
- mc->href->data, mc->base_href);
- }
-
- /* given HREF of the form: BASE "/" RELATIVE, extract the relative portion */
- relative = svn_urlpath__is_child(mc->base_href, mc->href->data, NULL);
- if (! relative) /* the paths are equal */
- relative = "";
-
- /* bump the resource */
- relative = svn_path_uri_decode(relative, pool);
- return bump_resource(mc, relative, mc->vsn_url->data, pool);
-}
-
-/* Determine whether we're receiving the expected XML response.
- Return CHILD when interested in receiving the child's contents
- or one of SVN_RA_NEON__XML_INVALID and SVN_RA_NEON__XML_DECLINE
- when respectively this is the incorrect response or
- the element (and its children) are uninteresting */
-static int validate_element(svn_ra_neon__xml_elmid parent,
- svn_ra_neon__xml_elmid child)
-{
- if ((child == ELEM_collection || child == ELEM_baseline)
- && parent != ELEM_resourcetype) {
- /* ### technically, they could occur elsewhere, but screw it */
- return SVN_RA_NEON__XML_INVALID;
- }
-
- switch (parent)
- {
- case ELEM_root:
- if (child == ELEM_merge_response)
- return child;
- else
- return SVN_RA_NEON__XML_INVALID;
-
- case ELEM_merge_response:
- if (child == ELEM_updated_set
- || child == ELEM_merged_set
- || child == ELEM_ignored_set)
- return child;
- else
- return SVN_RA_NEON__XML_DECLINE; /* any child is allowed */
-
- case ELEM_updated_set:
- case ELEM_merged_set:
- if (child == ELEM_response)
- return child;
- else
- return SVN_RA_NEON__XML_DECLINE; /* ignore if something else
- was in there */
-
- case ELEM_ignored_set:
- if (child == ELEM_href)
- return child;
- else
- return SVN_RA_NEON__XML_DECLINE; /* ignore if something else
- was in there */
-
- case ELEM_response:
- if (child == ELEM_href
- || child == ELEM_status
- || child == ELEM_propstat)
- return child;
- else if (child == ELEM_responsedescription)
- /* ### I think we want this... to save a message for the user */
- return SVN_RA_NEON__XML_DECLINE; /* valid, but we don't need to see it */
- else
- return SVN_RA_NEON__XML_DECLINE; /* ignore if something else
- was in there */
-
- case ELEM_propstat:
- if (child == ELEM_prop || child == ELEM_status)
- return child;
- else if (child == ELEM_responsedescription)
- /* ### I think we want this... to save a message for the user */
- return SVN_RA_NEON__XML_DECLINE; /* valid, but we don't need to see it */
- else
- return SVN_RA_NEON__XML_DECLINE; /* ignore if something else
- was in there */
-
- case ELEM_prop:
- if (child == ELEM_checked_in
- || child == ELEM_resourcetype
- || child == ELEM_version_name
- || child == ELEM_creationdate
- || child == ELEM_creator_displayname
- || child == ELEM_post_commit_err
- /* other props */)
- return child;
- else
- return SVN_RA_NEON__XML_DECLINE; /* ignore other props */
-
- case ELEM_checked_in:
- if (child == ELEM_href)
- return child;
- else
- return SVN_RA_NEON__XML_DECLINE; /* ignore if something else
- was in there */
-
- case ELEM_resourcetype:
- if (child == ELEM_collection || child == ELEM_baseline)
- return child;
- else
- return SVN_RA_NEON__XML_DECLINE; /* ignore if something else
- was in there */
-
- default:
- return SVN_RA_NEON__XML_DECLINE;
- }
-
- /* NOTREACHED */
-}
-
-static svn_error_t *
-start_element(int *elem, void *baton, int parent,
- const char *nspace, const char *name, const char **atts)
-{
- const svn_ra_neon__xml_elm_t *elm
- = svn_ra_neon__lookup_xml_elem(merge_elements, nspace, name);
- merge_ctx_t *mc = baton;
-
- *elem = elm ? validate_element(parent, elm->id) : SVN_RA_NEON__XML_DECLINE;
- if (*elem < 1) /* not a valid element */
- return SVN_NO_ERROR;
-
- switch (elm->id)
- {
- case ELEM_response:
- mc->response_has_error = FALSE;
-
- /* for each response (which corresponds to one resource), note that we
- haven't seen its resource type yet */
- mc->rtype = RTYPE_UNKNOWN;
-
- /* and we haven't seen these elements yet */
- mc->href->len = 0;
- mc->vsn_name->len = 0;
- mc->vsn_url->len = 0;
-
- /* FALLTHROUGH */
-
- case ELEM_ignored_set:
- case ELEM_checked_in:
- /* if we see an href "soon", then its parent is ELM */
- mc->href_parent = elm->id;
- break;
-
- case ELEM_updated_set:
- case ELEM_merged_set:
- mc->response_parent = elm->id;
- break;
-
- case ELEM_propstat:
- /* initialize the status so we can figure out if we ever saw a
- status element in the propstat */
- mc->status = 0;
- break;
-
- case ELEM_resourcetype:
- /* we've seen a DAV:resourcetype, so it will be "regular" unless we
- see something within this element */
- mc->rtype = RTYPE_REGULAR;
- break;
-
- case ELEM_collection:
- mc->rtype = RTYPE_COLLECTION;
- break;
-
- case ELEM_baseline:
- mc->rtype = RTYPE_BASELINE;
- break;
-
- default:
- /* one of: ELEM_href, ELEM_status, ELEM_prop,
- ELEM_version_name */
- break;
- }
-
- switch (elm->id)
- {
- case ELEM_href:
- case ELEM_status:
- case ELEM_version_name:
- case ELEM_post_commit_err:
- case ELEM_creationdate:
- case ELEM_creator_displayname:
- mc->want_cdata = mc->cdata;
- svn_stringbuf_setempty(mc->cdata);
- break;
-
- default:
- mc->want_cdata = NULL;
- break;
- }
-
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-end_element(void *baton, int state,
- const char *nspace, const char *name)
-{
- merge_ctx_t *mc = baton;
-
- switch (state)
- {
- case ELEM_href:
- switch (mc->href_parent)
- {
- case ELEM_ignored_set:
- add_ignored(mc, mc->cdata->data);
- break;
-
- case ELEM_response:
- /* we're now working on this href... */
- SVN_ERR(svn_ra_neon__copy_href(mc->href, mc->cdata->data,
- mc->scratchpool));
- break;
-
- case ELEM_checked_in:
- SVN_ERR(svn_ra_neon__copy_href(mc->vsn_url, mc->cdata->data,
- mc->scratchpool));
- break;
- }
- break;
-
- case ELEM_responsedescription:
- /* ### I don't think we'll see this right now, due to validate_element */
- /* ### remember this for error messages? */
- break;
-
- case ELEM_status:
- {
- ne_status hs;
-
- if (ne_parse_statusline(mc->cdata->data, &hs) != 0)
- mc->response_has_error = TRUE;
- else
- {
- mc->status = hs.code;
- if (hs.code != 200)
- {
- /* ### create an error structure? */
- mc->response_has_error = TRUE;
- }
- free(hs.reason_phrase);
- }
- if (mc->response_has_error)
- {
- /* ### fix this error value */
- return svn_error_create(APR_EGENERAL, NULL,
- _("The MERGE property response had an "
- "error status"));
- }
- }
- break;
-
- case ELEM_propstat:
- /* ### does Neon have a symbol for 200? */
- if (mc->status == 200 /* OK */)
- {
- /* ### what to do? reset all the data? */
- }
- /* ### else issue an error? status==0 means we never saw one */
- break;
-
- case ELEM_response:
- {
- /* the end of a DAV:response means that we've seen all the information
- related to this resource. process it. */
- SVN_ERR(handle_resource(mc, mc->scratchpool));
- svn_pool_clear(mc->scratchpool);
- }
- break;
-
- case ELEM_checked_in:
- /* When we leave a DAV:checked-in element, the parents are DAV:prop,
- DAV:propstat, then DAV:response. If we see a DAV:href "on the way
- out", then it is going to belong to the DAV:response. */
- mc->href_parent = ELEM_response;
- break;
-
- case ELEM_version_name:
- svn_stringbuf_set(mc->vsn_name, mc->cdata->data);
- break;
-
- case ELEM_post_commit_err:
- svn_stringbuf_set(mc->post_commit_err, mc->cdata->data);
- break;
-
- case ELEM_creationdate:
- svn_stringbuf_set(mc->committed_date, mc->cdata->data);
- break;
-
- case ELEM_creator_displayname:
- svn_stringbuf_set(mc->last_author, mc->cdata->data);
- break;
-
- default:
- /* one of: ELEM_updated_set, ELEM_merged_set, ELEM_ignored_set,
- ELEM_prop, ELEM_resourcetype, ELEM_collection, ELEM_baseline */
- break;
- }
-
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t * svn_ra_neon__assemble_locktoken_body(svn_stringbuf_t **body,
- apr_hash_t *lock_tokens,
- apr_pool_t *pool)
-{
- apr_hash_index_t *hi;
- apr_size_t buf_size;
- const char *closing_tag = "</S:lock-token-list>";
- apr_size_t closing_tag_size = strlen(closing_tag);
- apr_pool_t *tmppool = svn_pool_create(pool);
- apr_hash_t *xml_locks = apr_hash_make(tmppool);
- svn_stringbuf_t *lockbuf = svn_stringbuf_create
- ("<S:lock-token-list xmlns:S=\"" SVN_XML_NAMESPACE "\">" DEBUG_CR, pool);
-
- buf_size = lockbuf->len;
-
-#define SVN_LOCK "<S:lock>" DEBUG_CR
-#define SVN_LOCK_LEN sizeof(SVN_LOCK)-1
-#define SVN_LOCK_CLOSE "</S:lock>" DEBUG_CR
-#define SVN_LOCK_CLOSE_LEN sizeof(SVN_LOCK_CLOSE)-1
-#define SVN_LOCK_PATH "<S:lock-path>"
-#define SVN_LOCK_PATH_LEN sizeof(SVN_LOCK_PATH)-1
-#define SVN_LOCK_PATH_CLOSE "</S:lock-path>" DEBUG_CR
-#define SVN_LOCK_PATH_CLOSE_LEN sizeof(SVN_LOCK_CLOSE)-1
-#define SVN_LOCK_TOKEN "<S:lock-token>"
-#define SVN_LOCK_TOKEN_LEN sizeof(SVN_LOCK_TOKEN)-1
-#define SVN_LOCK_TOKEN_CLOSE "</S:lock-token>" DEBUG_CR
-#define SVN_LOCK_TOKEN_CLOSE_LEN sizeof(SVN_LOCK_TOKEN_CLOSE)-1
-
- /* First, figure out how much string data we're talking about,
- and allocate a stringbuf big enough to hold it all... we *never*
- want have the stringbuf do an auto-reallocation. While here,
- we'll be copying our hash of paths -> tokens into a hash of
- xml-escaped-paths -> tokens. */
- for (hi = apr_hash_first(tmppool, lock_tokens); hi; hi = apr_hash_next(hi))
- {
- const void *key;
- void *val;
- apr_ssize_t klen;
- svn_string_t lock_path;
- svn_stringbuf_t *lock_path_xml = NULL;
-
- apr_hash_this(hi, &key, &klen, &val);
-
- /* XML-escape our key and store it in our temporary hash. */
- lock_path.data = key;
- lock_path.len = klen;
- svn_xml_escape_cdata_string(&lock_path_xml, &lock_path, tmppool);
- apr_hash_set(xml_locks, lock_path_xml->data, lock_path_xml->len, val);
-
- /* Now, on with the stringbuf calculations. */
- buf_size += SVN_LOCK_LEN;
- buf_size += SVN_LOCK_PATH_LEN;
- buf_size += lock_path_xml->len;
- buf_size += SVN_LOCK_PATH_CLOSE_LEN;
- buf_size += SVN_LOCK_TOKEN_LEN;
- buf_size += strlen(val);
- buf_size += SVN_LOCK_TOKEN_CLOSE_LEN;
- buf_size += SVN_LOCK_CLOSE_LEN;
- }
-
- buf_size += closing_tag_size;
-
- svn_stringbuf_ensure(lockbuf, buf_size + 1);
-
- /* Now append all the temporary hash's keys and values into the
- stringbuf. This is better than doing apr_pstrcat() in a loop,
- because (1) there's no need to constantly re-alloc, and (2) the
- stringbuf already knows the end of the buffer, so there's no
- seek-time to the end of the string when appending. */
- for (hi = apr_hash_first(tmppool, xml_locks); hi; hi = apr_hash_next(hi))
- {
- const void *key;
- apr_ssize_t klen;
- void *val;
-
- apr_hash_this(hi, &key, &klen, &val);
-
- svn_stringbuf_appendcstr(lockbuf, SVN_LOCK);
- svn_stringbuf_appendcstr(lockbuf, SVN_LOCK_PATH);
- svn_stringbuf_appendbytes(lockbuf, key, klen);
- svn_stringbuf_appendcstr(lockbuf, SVN_LOCK_PATH_CLOSE);
- svn_stringbuf_appendcstr(lockbuf, SVN_LOCK_TOKEN);
- svn_stringbuf_appendcstr(lockbuf, val);
- svn_stringbuf_appendcstr(lockbuf, SVN_LOCK_TOKEN_CLOSE);
- svn_stringbuf_appendcstr(lockbuf, SVN_LOCK_CLOSE);
- }
-
- svn_stringbuf_appendcstr(lockbuf, closing_tag);
-
-#undef SVN_LOCK
-#undef SVN_LOCK_LEN
-#undef SVN_LOCK_CLOSE
-#undef SVN_LOCK_CLOSE_LEN
-#undef SVN_LOCK_PATH
-#undef SVN_LOCK_PATH_LEN
-#undef SVN_LOCK_PATH_CLOSE
-#undef SVN_LOCK_PATH_CLOSE_LEN
-#undef SVN_LOCK_TOKEN
-#undef SVN_LOCK_TOKEN_LEN
-#undef SVN_LOCK_TOKEN_CLOSE
-#undef SVN_LOCK_TOKEN_CLOSE_LEN
-
- *body = lockbuf;
-
- svn_pool_destroy(tmppool);
- return SVN_NO_ERROR;
-}
-
-
-/* ### FIXME: As of HTTPv2, this isn't necessarily merging an
- ### "activity". It might be merging a transaction. So,
- ### ACTIVITY_URL might be a transaction root URL, not an actual
- ### activity URL, etc. Probably should rename ACTIVITY_URL to
- ### MERGE_RESOURCE_URL or something. */
-svn_error_t * svn_ra_neon__merge_activity(svn_revnum_t *new_rev,
- const char **committed_date,
- const char **committed_author,
- const char **post_commit_err,
- svn_ra_neon__session_t *ras,
- const char *repos_url,
- const char *activity_url,
- apr_hash_t *valid_targets,
- apr_hash_t *lock_tokens,
- svn_boolean_t keep_locks,
- svn_boolean_t disable_merge_response,
- apr_pool_t *pool)
-{
- merge_ctx_t mc = { 0 };
- const char *body;
- apr_hash_t *extra_headers = NULL;
- svn_stringbuf_t *lockbuf = svn_stringbuf_create("", pool);
-
- mc.cdata = svn_stringbuf_create("", pool);
- mc.pool = pool;
- mc.scratchpool = svn_pool_create(pool);
- mc.base_href = repos_url;
- mc.rev = SVN_INVALID_REVNUM;
-
- mc.valid_targets = valid_targets;
- mc.push_prop = ras->callbacks->push_wc_prop;
- mc.cb_baton = ras->callback_baton;
-
- mc.href = MAKE_BUFFER(pool);
- mc.vsn_name = MAKE_BUFFER(pool);
- mc.vsn_url = MAKE_BUFFER(pool);
- mc.committed_date = MAKE_BUFFER(pool);
- mc.last_author = MAKE_BUFFER(pool);
- if (post_commit_err)
- mc.post_commit_err = MAKE_BUFFER(pool);
-
- if (disable_merge_response
- || (! keep_locks))
- {
- const char *value;
-
- value = apr_psprintf(pool, "%s %s",
- disable_merge_response ?
- SVN_DAV_OPTION_NO_MERGE_RESPONSE : "",
- keep_locks ?
- "" : SVN_DAV_OPTION_RELEASE_LOCKS);
-
- if (! extra_headers)
- extra_headers = apr_hash_make(pool);
- apr_hash_set(extra_headers, SVN_DAV_OPTIONS_HEADER, APR_HASH_KEY_STRING,
- value);
- }
-
- /* Need to marshal the whole [path->token] hash to the server as
- a string within the body of the MERGE request. */
- if ((lock_tokens != NULL)
- && (apr_hash_count(lock_tokens) > 0))
- SVN_ERR(svn_ra_neon__assemble_locktoken_body(&lockbuf, lock_tokens, pool));
-
- body = apr_psprintf(pool,
- "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
- "<D:merge xmlns:D=\"DAV:\">"
- "<D:source><D:href>%s</D:href></D:source>"
- "<D:no-auto-merge/><D:no-checkout/>"
- "<D:prop><D:checked-in/>"
- "<D:" SVN_DAV__VERSION_NAME "/><D:resourcetype/>"
- "<D:" SVN_DAV__CREATIONDATE "/><D:creator-displayname/>"
- "</D:prop>"
- "%s"
- "</D:merge>",
- activity_url, lockbuf->data);
-
- SVN_ERR(svn_ra_neon__parsed_request(ras, "MERGE", repos_url,
- body, 0, NULL,
- start_element,
- svn_ra_neon__xml_collect_cdata,
- end_element, &mc, extra_headers,
- NULL, FALSE, pool));
-
- /* return some commit properties to the caller. */
- if (new_rev)
- *new_rev = mc.rev;
- if (committed_date)
- *committed_date = mc.committed_date->len
- ? apr_pstrdup(pool, mc.committed_date->data) : NULL;
- if (committed_author)
- *committed_author = mc.last_author->len
- ? apr_pstrdup(pool, mc.last_author->data) : NULL;
- if (post_commit_err)
- *post_commit_err = mc.post_commit_err->len
- ? apr_pstrdup(pool, mc.post_commit_err->data) : NULL;
-
- svn_pool_destroy(mc.scratchpool);
-
- return NULL;
-}