diff options
Diffstat (limited to 'subversion/mod_dav_svn/version.c')
-rw-r--r-- | subversion/mod_dav_svn/version.c | 122 |
1 files changed, 109 insertions, 13 deletions
diff --git a/subversion/mod_dav_svn/version.c b/subversion/mod_dav_svn/version.c index b532085..98208a9 100644 --- a/subversion/mod_dav_svn/version.c +++ b/subversion/mod_dav_svn/version.c @@ -28,6 +28,7 @@ #include <http_log.h> #include <mod_dav.h> +#include "svn_hash.h" #include "svn_fs.h" #include "svn_xml.h" #include "svn_repos.h" @@ -37,7 +38,9 @@ #include "svn_props.h" #include "svn_dav.h" #include "svn_base64.h" +#include "svn_version.h" #include "private/svn_repos_private.h" +#include "private/svn_subr_private.h" #include "private/svn_dav_protocol.h" #include "private/svn_log.h" #include "private/svn_fspath.h" @@ -146,6 +149,9 @@ get_vsn_options(apr_pool_t *p, apr_text_header *phdr) apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_LOG_REVPROPS); apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS); apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY); + apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_INHERITED_PROPS); + apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_INLINE_PROPS); + apr_text_append(p, phdr, SVN_DAV_NS_DAV_SVN_REVERSE_FILE_REVS); /* Mergeinfo is a special case: here we merely say that the server * knows how to handle mergeinfo -- whether the repository does too * is a separate matter. @@ -192,6 +198,14 @@ get_option(const dav_resource *resource, } } + /* If we're allowed (by configuration) to do so, advertise support + for ephemeral transaction properties. */ + if (dav_svn__check_ephemeral_txnprops_support(r)) + { + apr_table_addn(r->headers_out, "DAV", + SVN_DAV_NS_DAV_SVN_EPHEMERAL_TXNPROPS); + } + if (resource->info->repos->fs) { svn_error_t *serr; @@ -230,10 +244,56 @@ get_option(const dav_resource *resource, } } + if (resource->info->repos->repos) + { + svn_error_t *serr; + svn_boolean_t has; + + serr = svn_repos_has_capability(resource->info->repos->repos, &has, + SVN_REPOS_CAPABILITY_MERGEINFO, + r->pool); + if (serr) + return dav_svn__convert_err + (serr, HTTP_INTERNAL_SERVER_ERROR, + "Error fetching repository capabilities", + resource->pool); + + apr_table_set(r->headers_out, SVN_DAV_REPOSITORY_MERGEINFO, + has ? "yes" : "no"); + } + /* Welcome to the 2nd generation of the svn HTTP protocol, now DeltaV-free! If we're configured to advise this support, do so. */ if (resource->info->repos->v2_protocol) { + int i; + svn_version_t *master_version = dav_svn__get_master_version(r); + dav_svn__bulk_upd_conf bulk_upd_conf = dav_svn__get_bulk_updates_flag(r); + + /* The list of Subversion's custom POSTs and which versions of + Subversion support them. We need this latter information + when acting as a WebDAV slave -- we don't want to claim + support for a POST type if the master server which will + actually have to handle it won't recognize it. + + Keep this in sync with what's handled in handle_post_request(). + */ + struct posts_versions_t { + const char *post_name; + svn_version_t min_version; + } posts_versions[] = { + { "create-txn", { 1, 7, 0, "" } }, + { "create-txn-with-props", { 1, 8, 0, "" } }, + }; + + /* Add the header which indicates that this server can handle + replay REPORTs submitted against an HTTP v2 revision resource. */ + apr_table_addn(r->headers_out, "DAV", + SVN_DAV_NS_DAV_SVN_REPLAY_REV_RESOURCE); + + /* Add a bunch of HTTP v2 headers which carry resource and + resource stub URLs that the client can use to naively build + addressable resources. */ 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, "/", @@ -256,6 +316,26 @@ get_option(const dav_resource *resource, 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)); + 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"); + + /* Report the supported POST types. */ + for (i = 0; i < sizeof(posts_versions)/sizeof(posts_versions[0]); ++i) + { + /* If we're proxying to a master server and its version + number is declared, we can selectively filter out POST + types that it doesn't support. */ + if (master_version + && (! svn_version__at_least(master_version, + posts_versions[i].min_version.major, + posts_versions[i].min_version.minor, + posts_versions[i].min_version.patch))) + continue; + + apr_table_addn(r->headers_out, SVN_DAV_SUPPORTED_POSTS_HEADER, + apr_pstrdup(resource->pool, posts_versions[i].post_name)); + } } return NULL; @@ -398,7 +478,7 @@ dav_svn__checkout(dav_resource *resource, shared_activity = apr_pstrdup(resource->info->r->pool, uuid_buf); derr = dav_svn__create_txn(resource->info->repos, &shared_txn_name, - resource->info->r->pool); + NULL, resource->info->r->pool); if (derr) return derr; derr = dav_svn__store_activity(resource->info->repos, @@ -953,8 +1033,11 @@ dav_svn__checkin(dav_resource *resource, if (serr) { + int status; + if (serr->apr_err == SVN_ERR_FS_CONFLICT) { + status = HTTP_CONFLICT; msg = apr_psprintf(resource->pool, "A conflict occurred during the CHECKIN " "processing. The problem occurred with " @@ -962,10 +1045,12 @@ dav_svn__checkin(dav_resource *resource, conflict_msg); } else - msg = "An error occurred while committing the transaction."; + { + status = HTTP_INTERNAL_SERVER_ERROR; + msg = "An error occurred while committing the transaction."; + } - return dav_svn__convert_err(serr, HTTP_CONFLICT, msg, - resource->pool); + return dav_svn__convert_err(serr, status, msg, resource->pool); } else { @@ -1093,6 +1178,10 @@ deliver_report(request_rec *r, { return dav_svn__get_deleted_rev_report(resource, doc, output); } + else if (strcmp(doc->root->name, SVN_DAV__INHERITED_PROPS_REPORT) == 0) + { + return dav_svn__get_inherited_props_report(resource, doc, output); + } /* NOTE: if you add a report, don't forget to add it to the * dav_svn__reports_list[] array. */ @@ -1138,7 +1227,8 @@ make_activity(dav_resource *resource) SVN_DAV_ERROR_NAMESPACE, SVN_DAV_ERROR_TAG); - err = dav_svn__create_txn(resource->info->repos, &txn_name, resource->pool); + err = dav_svn__create_txn(resource->info->repos, &txn_name, + NULL, resource->pool); if (err != NULL) return err; @@ -1180,7 +1270,7 @@ dav_svn__build_lock_hash(apr_hash_t **locks, if (! doc) { *locks = hash; - return SVN_NO_ERROR; + return NULL; } /* Sanity check. */ @@ -1191,7 +1281,7 @@ dav_svn__build_lock_hash(apr_hash_t **locks, definitely no lock-tokens to harvest. This is likely a request from an old client. */ *locks = hash; - return SVN_NO_ERROR; + return NULL; } if ((doc->root->ns == ns) @@ -1217,7 +1307,7 @@ dav_svn__build_lock_hash(apr_hash_t **locks, if (! child) { *locks = hash; - return SVN_NO_ERROR; + return NULL; } /* Then look for N different <lock> structures within. */ @@ -1243,7 +1333,7 @@ dav_svn__build_lock_hash(apr_hash_t **locks, lockpath = svn_fspath__join(path_prefix, cdata, pool); if (lockpath && locktoken) { - apr_hash_set(hash, lockpath, APR_HASH_KEY_STRING, locktoken); + svn_hash_sets(hash, lockpath, locktoken); lockpath = NULL; locktoken = NULL; } @@ -1253,7 +1343,7 @@ dav_svn__build_lock_hash(apr_hash_t **locks, locktoken = dav_xml_get_cdata(lfchild, pool, 1); if (lockpath && *locktoken) { - apr_hash_set(hash, lockpath, APR_HASH_KEY_STRING, locktoken); + svn_hash_sets(hash, lockpath, locktoken); lockpath = NULL; locktoken = NULL; } @@ -1262,7 +1352,7 @@ dav_svn__build_lock_hash(apr_hash_t **locks, } *locks = hash; - return SVN_NO_ERROR; + return NULL; } @@ -1455,8 +1545,11 @@ merge(dav_resource *target, if (serr) { const char *msg; + int status; + if (serr->apr_err == SVN_ERR_FS_CONFLICT) { + status = HTTP_CONFLICT; /* ### we need to convert the conflict path into a URI */ msg = apr_psprintf(pool, "A conflict occurred during the MERGE " @@ -1465,9 +1558,12 @@ merge(dav_resource *target, conflict); } else - msg = "An error occurred while committing the transaction."; + { + status = HTTP_INTERNAL_SERVER_ERROR; + msg = "An error occurred while committing the transaction."; + } - return dav_svn__convert_err(serr, HTTP_CONFLICT, msg, pool); + return dav_svn__convert_err(serr, status, msg, pool); } else { |