summaryrefslogtreecommitdiff
path: root/subversion/mod_dav_svn/version.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/mod_dav_svn/version.c')
-rw-r--r--subversion/mod_dav_svn/version.c260
1 files changed, 115 insertions, 145 deletions
diff --git a/subversion/mod_dav_svn/version.c b/subversion/mod_dav_svn/version.c
index 98208a9..638cae9 100644
--- a/subversion/mod_dav_svn/version.c
+++ b/subversion/mod_dav_svn/version.c
@@ -178,26 +178,33 @@ get_option(const dav_resource *resource,
request_rec *r = resource->info->r;
const char *repos_root_uri =
dav_svn__build_uri(resource->info->repos, DAV_SVN__BUILD_URI_PUBLIC,
- SVN_IGNORED_REVNUM, "", 0, resource->pool);
+ SVN_IGNORED_REVNUM, "", FALSE /* add_href */,
+ resource->pool);
/* ### DAV:version-history-collection-set */
- if (elem->ns == APR_XML_NS_DAV_ID)
+ if (elem->ns != APR_XML_NS_DAV_ID
+ || strcmp(elem->name, "activity-collection-set") != 0)
{
- if (strcmp(elem->name, "activity-collection-set") == 0)
- {
- apr_text_append(resource->pool, option,
- "<D:activity-collection-set>");
- apr_text_append(resource->pool, option,
- dav_svn__build_uri(resource->info->repos,
- DAV_SVN__BUILD_URI_ACT_COLLECTION,
- SVN_INVALID_REVNUM, NULL,
- 1 /* add_href */,
- resource->pool));
- apr_text_append(resource->pool, option,
- "</D:activity-collection-set>");
- }
+ /* We don't know about other options (yet).
+
+ If we ever add multiple option request keys we should
+ just write the requested option value and make sure
+ we set the headers *once*. */
+ return NULL;
}
+ apr_text_append(resource->pool, option,
+ "<D:activity-collection-set>");
+
+ apr_text_append(resource->pool, option,
+ dav_svn__build_uri(resource->info->repos,
+ DAV_SVN__BUILD_URI_ACT_COLLECTION,
+ SVN_INVALID_REVNUM, NULL,
+ TRUE /* add_href */,
+ resource->pool));
+ apr_text_append(resource->pool, option,
+ "</D:activity-collection-set>");
+
/* If we're allowed (by configuration) to do so, advertise support
for ephemeral transaction properties. */
if (dav_svn__check_ephemeral_txnprops_support(r))
@@ -297,25 +304,25 @@ get_option(const dav_resource *resource,
apr_table_set(r->headers_out, SVN_DAV_ROOT_URI_HEADER, repos_root_uri);
apr_table_set(r->headers_out, SVN_DAV_ME_RESOURCE_HEADER,
apr_pstrcat(resource->pool, repos_root_uri, "/",
- dav_svn__get_me_resource_uri(r), (char *)NULL));
+ dav_svn__get_me_resource_uri(r), SVN_VA_NULL));
apr_table_set(r->headers_out, SVN_DAV_REV_ROOT_STUB_HEADER,
apr_pstrcat(resource->pool, repos_root_uri, "/",
- dav_svn__get_rev_root_stub(r), (char *)NULL));
+ dav_svn__get_rev_root_stub(r), SVN_VA_NULL));
apr_table_set(r->headers_out, SVN_DAV_REV_STUB_HEADER,
apr_pstrcat(resource->pool, repos_root_uri, "/",
- dav_svn__get_rev_stub(r), (char *)NULL));
+ dav_svn__get_rev_stub(r), SVN_VA_NULL));
apr_table_set(r->headers_out, SVN_DAV_TXN_ROOT_STUB_HEADER,
apr_pstrcat(resource->pool, repos_root_uri, "/",
- dav_svn__get_txn_root_stub(r), (char *)NULL));
+ dav_svn__get_txn_root_stub(r), SVN_VA_NULL));
apr_table_set(r->headers_out, SVN_DAV_TXN_STUB_HEADER,
apr_pstrcat(resource->pool, repos_root_uri, "/",
- dav_svn__get_txn_stub(r), (char *)NULL));
+ dav_svn__get_txn_stub(r), SVN_VA_NULL));
apr_table_set(r->headers_out, SVN_DAV_VTXN_ROOT_STUB_HEADER,
apr_pstrcat(resource->pool, repos_root_uri, "/",
- dav_svn__get_vtxn_root_stub(r), (char *)NULL));
+ dav_svn__get_vtxn_root_stub(r), SVN_VA_NULL));
apr_table_set(r->headers_out, SVN_DAV_VTXN_STUB_HEADER,
apr_pstrcat(resource->pool, repos_root_uri, "/",
- dav_svn__get_vtxn_stub(r), (char *)NULL));
+ dav_svn__get_vtxn_stub(r), SVN_VA_NULL));
apr_table_set(r->headers_out, SVN_DAV_ALLOW_BULK_UPDATES,
bulk_upd_conf == CONF_BULKUPD_ON ? "On" :
bulk_upd_conf == CONF_BULKUPD_OFF ? "Off" : "Prefer");
@@ -395,11 +402,9 @@ vsn_control(dav_resource *resource, const char *target)
/* Only allow a NULL target, which means an create an 'empty' VCR. */
if (target != NULL)
- return dav_svn__new_error_tag(resource->pool, HTTP_NOT_IMPLEMENTED,
+ return dav_svn__new_error_svn(resource->pool, HTTP_NOT_IMPLEMENTED,
SVN_ERR_UNSUPPORTED_FEATURE,
- "vsn_control called with non-null target.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "vsn_control called with non-null target");
/* This is kind of silly. The docstring for this callback says it's
supposed to "put a resource under version control". But in
@@ -445,20 +450,16 @@ dav_svn__checkout(dav_resource *resource,
return NULL;
if (resource->type != DAV_RESOURCE_TYPE_REGULAR)
- return dav_svn__new_error_tag(resource->pool, HTTP_METHOD_NOT_ALLOWED,
+ return dav_svn__new_error_svn(resource->pool, HTTP_METHOD_NOT_ALLOWED,
SVN_ERR_UNSUPPORTED_FEATURE,
"auto-checkout attempted on non-regular "
- "version-controlled resource.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "version-controlled resource");
if (resource->baselined)
- return dav_svn__new_error_tag(resource->pool, HTTP_METHOD_NOT_ALLOWED,
+ return dav_svn__new_error_svn(resource->pool, HTTP_METHOD_NOT_ALLOWED,
SVN_ERR_UNSUPPORTED_FEATURE,
"auto-checkout attempted on baseline "
- "collection, which is not supported.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "collection, which is not supported");
/* See if the shared activity already exists. */
apr_err = apr_pool_userdata_get(&data,
@@ -540,51 +541,41 @@ dav_svn__checkout(dav_resource *resource,
if (resource->type != DAV_RESOURCE_TYPE_VERSION)
{
- return dav_svn__new_error_tag(resource->pool, HTTP_METHOD_NOT_ALLOWED,
+ return dav_svn__new_error_svn(resource->pool, HTTP_METHOD_NOT_ALLOWED,
SVN_ERR_UNSUPPORTED_FEATURE,
"CHECKOUT can only be performed on a "
- "version resource [at this time].",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "version resource");
}
if (create_activity)
{
- return dav_svn__new_error_tag(resource->pool, HTTP_NOT_IMPLEMENTED,
+ return dav_svn__new_error_svn(resource->pool, HTTP_NOT_IMPLEMENTED,
SVN_ERR_UNSUPPORTED_FEATURE,
"CHECKOUT cannot create an activity at "
- "this time. Use MKACTIVITY first.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "this time. Use MKACTIVITY first");
}
if (is_unreserved)
{
- return dav_svn__new_error_tag(resource->pool, HTTP_NOT_IMPLEMENTED,
+ return dav_svn__new_error_svn(resource->pool, HTTP_NOT_IMPLEMENTED,
SVN_ERR_UNSUPPORTED_FEATURE,
"Unreserved checkouts are not yet "
"available. A version history may not be "
"checked out more than once, into a "
- "specific activity.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "specific activity");
}
if (activities == NULL)
{
- return dav_svn__new_error_tag(resource->pool, HTTP_CONFLICT,
+ return dav_svn__new_error_svn(resource->pool, HTTP_CONFLICT,
SVN_ERR_INCOMPLETE_DATA,
"An activity must be provided for "
- "checkout.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "checkout");
}
/* assert: nelts > 0. the below check effectively means > 1. */
if (activities->nelts != 1)
{
- return dav_svn__new_error_tag(resource->pool, HTTP_CONFLICT,
+ return dav_svn__new_error_svn(resource->pool, HTTP_CONFLICT,
SVN_ERR_INCORRECT_PARAMS,
"Only one activity may be specified within "
- "the CHECKOUT.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "the CHECKOUT");
}
serr = dav_svn__simple_parse_uri(&parse, resource,
@@ -600,21 +591,17 @@ dav_svn__checkout(dav_resource *resource,
}
if (parse.activity_id == NULL)
{
- return dav_svn__new_error_tag(resource->pool, HTTP_CONFLICT,
+ return dav_svn__new_error_svn(resource->pool, HTTP_CONFLICT,
SVN_ERR_INCORRECT_PARAMS,
- "The provided href is not an activity URI.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "The provided href is not an activity URI");
}
if ((txn_name = dav_svn__get_txn(resource->info->repos,
parse.activity_id)) == NULL)
{
- return dav_svn__new_error_tag(resource->pool, HTTP_CONFLICT,
+ return dav_svn__new_error_svn(resource->pool, HTTP_CONFLICT,
SVN_ERR_APMOD_ACTIVITY_NOT_FOUND,
- "The specified activity does not exist.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "The specified activity does not exist");
}
/* verify the specified version resource is the "latest", thus allowing
@@ -642,13 +629,11 @@ dav_svn__checkout(dav_resource *resource,
if (resource->info->root.rev != youngest)
{
- return dav_svn__new_error_tag(resource->pool, HTTP_CONFLICT,
+ return dav_svn__new_error_svn(resource->pool, HTTP_CONFLICT,
SVN_ERR_APMOD_BAD_BASELINE,
"The specified baseline is not the "
"latest baseline, so it may not be "
- "checked out.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "checked out");
}
/* ### hmm. what if the transaction root's revision is different
@@ -742,11 +727,9 @@ dav_svn__checkout(dav_resource *resource,
{
/* The item being modified is older than the one in the
transaction. The client is out of date. */
- return dav_svn__new_error_tag
+ return dav_svn__new_error_svn
(resource->pool, HTTP_CONFLICT, SVN_ERR_FS_CONFLICT,
- "resource out of date; try updating",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "resource out of date; try updating");
}
else if (resource->info->root.rev > txn_created_rev)
{
@@ -754,42 +737,25 @@ dav_svn__checkout(dav_resource *resource,
revision than the one in the transaction. We'll
check to see if they are still the same node, and if
not, return an error. */
- const svn_fs_id_t *url_noderev_id, *txn_noderev_id;
-
- if ((serr = svn_fs_node_id(&txn_noderev_id, txn_root,
- resource->info->repos_path,
- resource->pool)))
+ svn_fs_node_relation_t node_relation;
+ if ((serr = svn_fs_node_relation(&node_relation, txn_root,
+ resource->info->repos_path,
+ resource->info->root.root,
+ resource->info->repos_path,
+ resource->pool)))
{
- err = dav_svn__new_error_tag
+ err = dav_svn__new_error_svn
(resource->pool, HTTP_CONFLICT, serr->apr_err,
"Unable to fetch the node revision id of the version "
- "resource within the transaction.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "resource within the revision");
svn_error_clear(serr);
return err;
}
- if ((serr = svn_fs_node_id(&url_noderev_id,
- resource->info->root.root,
- resource->info->repos_path,
- resource->pool)))
+ if (node_relation != svn_fs_node_unchanged)
{
- err = dav_svn__new_error_tag
- (resource->pool, HTTP_CONFLICT, serr->apr_err,
- "Unable to fetch the node revision id of the version "
- "resource within the revision.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
- svn_error_clear(serr);
- return err;
- }
- if (svn_fs_compare_ids(url_noderev_id, txn_noderev_id) != 0)
- {
- return dav_svn__new_error_tag
+ return dav_svn__new_error_svn
(resource->pool, HTTP_CONFLICT, SVN_ERR_FS_CONFLICT,
- "version resource newer than txn (restart the commit)",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "version resource newer than txn (restart the commit)");
}
}
}
@@ -806,11 +772,9 @@ static dav_error *
uncheckout(dav_resource *resource)
{
if (resource->type != DAV_RESOURCE_TYPE_WORKING)
- return dav_svn__new_error_tag(resource->pool, HTTP_INTERNAL_SERVER_ERROR,
+ return dav_svn__new_error_svn(resource->pool, HTTP_INTERNAL_SERVER_ERROR,
SVN_ERR_UNSUPPORTED_FEATURE,
- "UNCHECKOUT called on non-working resource.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "UNCHECKOUT called on non-working resource");
/* Try to abort the txn if it exists; but don't try too hard. :-) */
if (resource->info->root.txn)
@@ -877,7 +841,7 @@ cleanup_deltify(void *data)
subpool, then destroy it before exiting. */
apr_pool_t *subpool = svn_pool_create(cdb->pool);
- err = svn_repos_open2(&repos, cdb->repos_path, NULL, subpool);
+ err = svn_repos_open3(&repos, cdb->repos_path, NULL, subpool, subpool);
if (err)
{
ap_log_perror(APLOG_MARK, APLOG_ERR, err->apr_err, cdb->pool,
@@ -949,11 +913,9 @@ dav_svn__checkin(dav_resource *resource,
txn? Many txns? Etc.) */
if (resource->type != DAV_RESOURCE_TYPE_WORKING)
- return dav_svn__new_error_tag(resource->pool, HTTP_INTERNAL_SERVER_ERROR,
+ return dav_svn__new_error_svn(resource->pool, HTTP_INTERNAL_SERVER_ERROR,
SVN_ERR_UNSUPPORTED_FEATURE,
- "CHECKIN called on non-working resource.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "CHECKIN called on non-working resource");
/* If the global autoversioning activity still exists, that means
nobody's committed it yet. */
@@ -1010,7 +972,7 @@ dav_svn__checkin(dav_resource *resource,
{
const char *post_commit_err = svn_repos__post_commit_error_str
(serr, resource->pool);
- ap_log_perror(APLOG_MARK, APLOG_ERR, serr->apr_err,
+ ap_log_perror(APLOG_MARK, APLOG_ERR, APR_EGENERAL,
resource->pool,
"commit of r%ld succeeded, but an error occurred "
"after the commit: '%s'",
@@ -1079,7 +1041,7 @@ dav_svn__checkin(dav_resource *resource,
uri = dav_svn__build_uri(resource->info->repos,
DAV_SVN__BUILD_URI_VERSION,
new_rev, resource->info->repos_path,
- 0, resource->pool);
+ FALSE /* add_href */, resource->pool);
err = dav_svn__create_version_resource(version_resource, uri,
resource->pool);
@@ -1130,12 +1092,16 @@ static dav_error *
deliver_report(request_rec *r,
const dav_resource *resource,
const apr_xml_doc *doc,
- ap_filter_t *output)
+ ap_filter_t *unused)
{
int ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE);
if (doc->root->ns == ns)
{
+ dav_svn__output *output;
+
+ output = dav_svn__output_create(resource->info->r, resource->pool);
+
/* ### note that these report names should have symbols... */
if (strcmp(doc->root->name, "update-report") == 0)
@@ -1188,11 +1154,9 @@ deliver_report(request_rec *r,
}
/* ### what is a good error for an unknown report? */
- return dav_svn__new_error_tag(resource->pool, HTTP_NOT_IMPLEMENTED,
+ return dav_svn__new_error_svn(resource->pool, HTTP_NOT_IMPLEMENTED,
SVN_ERR_UNSUPPORTED_FEATURE,
- "The requested report is unknown.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "The requested report is unknown");
}
@@ -1219,13 +1183,11 @@ make_activity(dav_resource *resource)
/* sanity check: make sure the resource is a valid activity, in
case an older mod_dav doesn't do the check for us. */
if (! can_be_activity(resource))
- return dav_svn__new_error_tag(resource->pool, HTTP_FORBIDDEN,
+ return dav_svn__new_error_svn(resource->pool, HTTP_FORBIDDEN,
SVN_ERR_APMOD_MALFORMED_URI,
"Activities cannot be created at that "
"location; query the "
- "DAV:activity-collection-set property.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "DAV:activity-collection-set property");
err = dav_svn__create_txn(resource->info->repos, &txn_name,
NULL, resource->pool);
@@ -1396,6 +1358,23 @@ dav_svn__push_locks(dav_resource *resource,
return NULL;
}
+/* Implements svn_fs_lock_callback_t. */
+static svn_error_t *
+unlock_many_cb(void *lock_baton,
+ const char *path,
+ const svn_lock_t *lock,
+ svn_error_t *fs_err,
+ apr_pool_t *pool)
+{
+ request_rec *r = lock_baton;
+
+ if (fs_err)
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, fs_err->apr_err, r,
+ "%s", fs_err->message);
+
+ return SVN_NO_ERROR;
+}
+
/* Helper for merge(). Free every lock in LOCKS. The locks
live in REPOS. Log any errors for REQUEST. Use POOL for temporary
@@ -1406,28 +1385,16 @@ release_locks(apr_hash_t *locks,
request_rec *r,
apr_pool_t *pool)
{
- apr_hash_index_t *hi;
- const void *key;
- void *val;
apr_pool_t *subpool = svn_pool_create(pool);
svn_error_t *err;
- for (hi = apr_hash_first(pool, locks); hi; hi = apr_hash_next(hi))
- {
- svn_pool_clear(subpool);
- apr_hash_this(hi, &key, NULL, &val);
-
- /* The lock may be stolen or broken sometime between
- svn_fs_commit_txn() and this post-commit cleanup. So ignore
- any errors from this command; just free as many locks as we can. */
- err = svn_repos_fs_unlock(repos, key, val, FALSE, subpool);
+ err = svn_repos_fs_unlock_many(repos, locks, FALSE, unlock_many_cb, r,
+ subpool, subpool);
- if (err) /* If we got an error, just log it and move along. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, err->apr_err, r,
- "%s", err->message);
-
- svn_error_clear(err);
- }
+ if (err) /* If we got an error, just log it and move along. */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, err->apr_err, r,
+ "%s", err->message);
+ svn_error_clear(err);
svn_pool_destroy(subpool);
@@ -1441,7 +1408,7 @@ merge(dav_resource *target,
int no_auto_merge,
int no_checkout,
apr_xml_elem *prop_elem,
- ap_filter_t *output)
+ ap_filter_t *unused)
{
apr_pool_t *pool;
dav_error *err;
@@ -1452,6 +1419,7 @@ merge(dav_resource *target,
svn_revnum_t new_rev;
apr_hash_t *locks;
svn_boolean_t disable_merge_response = FALSE;
+ dav_svn__output *output;
/* We'll use the target's pool for our operation. We happen to know that
it matches the request pool, which (should) have the proper lifetime. */
@@ -1464,22 +1432,18 @@ merge(dav_resource *target,
|| (source->type == DAV_RESOURCE_TYPE_PRIVATE
&& source->info->restype == DAV_SVN_RESTYPE_TXN_COLLECTION)))
{
- return dav_svn__new_error_tag(pool, HTTP_METHOD_NOT_ALLOWED,
+ return dav_svn__new_error_svn(pool, HTTP_METHOD_NOT_ALLOWED,
SVN_ERR_INCORRECT_PARAMS,
"MERGE can only be performed using an "
"activity or transaction resource as the "
- "source.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "source");
}
if (! source->exists)
{
- return dav_svn__new_error_tag(pool, HTTP_METHOD_NOT_ALLOWED,
+ return dav_svn__new_error_svn(pool, HTTP_METHOD_NOT_ALLOWED,
SVN_ERR_INCORRECT_PARAMS,
"MERGE activity or transaction resource "
- "does not exist.",
- SVN_DAV_ERROR_NAMESPACE,
- SVN_DAV_ERROR_TAG);
+ "does not exist");
}
/* Before attempting the final commit, we need to push any incoming
@@ -1528,6 +1492,11 @@ merge(dav_resource *target,
### client some other way than hijacking the post-commit
### error message.*/
post_commit_err = svn_repos__post_commit_error_str(serr, pool);
+ ap_log_perror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, pool,
+ "commit of r%ld succeeded, but an error occurred "
+ "after the commit: '%s'",
+ new_rev,
+ post_commit_err);
svn_error_clear(serr);
serr = SVN_NO_ERROR;
}
@@ -1620,6 +1589,7 @@ merge(dav_resource *target,
}
/* process the response for the new revision. */
+ output = dav_svn__output_create(target->info->r, pool);
return dav_svn__merge_response(output, source->info->repos, new_rev,
post_commit_err, prop_elem,
disable_merge_response, pool);