📄 version.c
字号:
if (strcmp(doc->root->name, "update-report") == 0) { return dav_svn__update_report(resource, doc, output); } else if (strcmp(doc->root->name, "log-report") == 0) { return dav_svn__log_report(resource, doc, output); } else if (strcmp(doc->root->name, "dated-rev-report") == 0) { return dav_svn__drev_report(resource, doc, output); } else if (strcmp(doc->root->name, "get-locations") == 0) { return dav_svn__get_locations_report(resource, doc, output); } else if (strcmp(doc->root->name, "file-revs-report") == 0) { return dav_svn__file_revs_report(resource, doc, output); } else if (strcmp(doc->root->name, "get-locks-report") == 0) { return dav_svn__get_locks_report(resource, doc, output); } else if (strcmp(doc->root->name, "replay-report") == 0) { return dav_svn__replay_report(resource, doc, output); } /* NOTE: if you add a report, don't forget to add it to the * avail_reports[] array at the top of this file. */ } /* ### what is a good error for an unknown report? */ return dav_svn__new_error_tag(resource->pool, HTTP_NOT_IMPLEMENTED, SVN_ERR_UNSUPPORTED_FEATURE, "The requested report is unknown.", SVN_DAV_ERROR_NAMESPACE, SVN_DAV_ERROR_TAG);}static int dav_svn_can_be_activity(const dav_resource *resource){ /* If our resource is marked as auto_checked_out'd, then we allow this to * be an activity URL. Otherwise, it must be a real activity URL that * doesn't already exist. */ return (resource->info->auto_checked_out == TRUE || (resource->type == DAV_RESOURCE_TYPE_ACTIVITY && !resource->exists));}static dav_error *dav_svn_make_activity(dav_resource *resource){ const char *activity_id = resource->info->root.activity_id; const char *txn_name; dav_error *err; /* sanity check: make sure the resource is a valid activity, in case an older mod_dav doesn't do the check for us. */ if (! dav_svn_can_be_activity(resource)) return dav_svn__new_error_tag(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); err = dav_svn_create_activity(resource->info->repos, &txn_name, resource->pool); if (err != NULL) return err; err = dav_svn_store_activity(resource->info->repos, activity_id, txn_name); if (err != NULL) return err; /* everything is happy. update the resource */ resource->info->root.txn_name = txn_name; resource->exists = 1; return NULL;}dav_error *dav_svn__build_lock_hash(apr_hash_t **locks, request_rec *r, const char *path_prefix, apr_pool_t *pool){ apr_status_t apr_err; dav_error *derr; void *data = NULL; apr_xml_doc *doc = NULL; apr_xml_elem *child, *lockchild; int ns; apr_hash_t *hash = apr_hash_make(pool); /* Grab the request body out of r->pool, as it contains all of the lock tokens. It should have been stashed already by our custom input filter. */ apr_err = apr_pool_userdata_get(&data, "svn-request-body", r->pool); if (apr_err) return dav_svn_convert_err(svn_error_create(apr_err, 0, NULL), HTTP_INTERNAL_SERVER_ERROR, "Error fetching pool userdata.", pool); doc = data; if (! doc) { *locks = hash; return SVN_NO_ERROR; } /* Sanity check. */ ns = dav_svn_find_ns(doc->namespaces, SVN_XML_NAMESPACE); if (ns == -1) { /* If there's no svn: namespace in the body, then there are definitely no lock-tokens to harvest. This is likely a request from an old client. */ *locks = hash; return SVN_NO_ERROR; } if ((doc->root->ns == ns) && (strcmp(doc->root->name, "lock-token-list") == 0)) { child = doc->root; } else { /* Search doc's children until we find the <lock-token-list>. */ for (child = doc->root->first_child; child != NULL; child = child->next) { /* if this element isn't one of ours, then skip it */ if (child->ns != ns) continue; if (strcmp(child->name, "lock-token-list") == 0) break; } } /* Did we find what we were looking for? */ if (! child) { *locks = hash; return SVN_NO_ERROR; } /* Then look for N different <lock> structures within. */ for (lockchild = child->first_child; lockchild != NULL; lockchild = lockchild->next) { const char *lockpath = NULL, *locktoken = NULL; apr_xml_elem *lfchild; if (strcmp(lockchild->name, "lock") != 0) continue; for (lfchild = lockchild->first_child; lfchild != NULL; lfchild = lfchild->next) { if (strcmp(lfchild->name, "lock-path") == 0) { const char *cdata = dav_xml_get_cdata(lfchild, pool, 0); if ((derr = dav_svn__test_canonical(cdata, pool))) return derr; /* Create an absolute fs-path */ lockpath = svn_path_join(path_prefix, cdata, pool); if (lockpath && locktoken) { apr_hash_set(hash, lockpath, APR_HASH_KEY_STRING, locktoken); lockpath = NULL; locktoken = NULL; } } else if (strcmp(lfchild->name, "lock-token") == 0) { locktoken = dav_xml_get_cdata(lfchild, pool, 1); if (lockpath && *locktoken) { apr_hash_set(hash, lockpath, APR_HASH_KEY_STRING, locktoken); lockpath = NULL; locktoken = NULL; } } } } *locks = hash; return SVN_NO_ERROR;}dav_error *dav_svn__push_locks(dav_resource *resource, apr_hash_t *locks, apr_pool_t *pool){ svn_fs_access_t *fsaccess; apr_hash_index_t *hi; svn_error_t *serr; serr = svn_fs_get_access(&fsaccess, resource->info->repos->fs); if (serr) { /* If an authenticated user name was attached to the request, then dav_svn_get_resource() should have already noticed and created an fs_access_t in the filesystem. */ return dav_svn__sanitize_error(serr, "Lock token(s) in request, but " "missing an user name", HTTP_BAD_REQUEST, resource->info->r); } for (hi = apr_hash_first(pool, locks); hi; hi = apr_hash_next(hi)) { const char *token; void *val; apr_hash_this(hi, NULL, NULL, &val); token = val; serr = svn_fs_access_add_lock_token(fsaccess, token); if (serr) return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Error pushing token into filesystem.", pool); } return NULL;}/* Helper for dav_svn_merge(). Free every lock in LOCKS. The locks live in REPOS. Log any errors for REQUEST. Use POOL for temporary work.*/static svn_error_t *release_locks(apr_hash_t *locks, svn_repos_t *repos, 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); 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); return SVN_NO_ERROR;}static dav_error *dav_svn_merge(dav_resource *target, dav_resource *source, int no_auto_merge, int no_checkout, apr_xml_elem *prop_elem, ap_filter_t *output){ apr_pool_t *pool; dav_error *err; svn_fs_txn_t *txn; const char *conflict; svn_error_t *serr; char *post_commit_err = NULL; svn_revnum_t new_rev; apr_hash_t *locks; svn_boolean_t disable_merge_response = FALSE; /* 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. */ pool = target->pool; /* ### what to verify on the target? */ /* ### anything else for the source? */ if (source->type != DAV_RESOURCE_TYPE_ACTIVITY) { return dav_svn__new_error_tag(pool, HTTP_METHOD_NOT_ALLOWED, SVN_ERR_INCORRECT_PARAMS, "MERGE can only be performed using an " "activity as the source [at this time].", SVN_DAV_ERROR_NAMESPACE, SVN_DAV_ERROR_TAG); } /* Before attempting the final commit, we need to push any incoming lock-tokens into the filesystem's access_t. Normally they come in via 'If:' header, and dav_svn_get_resource() automatically notices them and does this work for us. In the case of MERGE, however, svn clients are sending them in the request body. */ err = dav_svn__build_lock_hash(&locks, target->info->r, target->info->repos_path, pool); if (err != NULL) return err; if (apr_hash_count(locks)) { err = dav_svn__push_locks(source, locks, pool); if (err != NULL) return err; } /* We will ignore no_auto_merge and no_checkout. We can't do those, but the client has no way to assert that we *should* do them. This should be fine because, presumably, the client has no way to do the various checkouts and things that would necessitate an auto-merge or checkout during the MERGE processing. */ /* open the transaction that we're going to commit. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -