📄 repos.c
字号:
/* ### what to do with LABEL and USE_CHECKED_IN ?? */ comb->res.type = DAV_RESOURCE_TYPE_WORKING; comb->res.working = TRUE; comb->res.versioned = TRUE; comb->res.baselined = TRUE; if ((slash = ap_strchr_c(path, '/')) == NULL || slash == path || slash[1] == '\0') return TRUE; comb->priv.root.activity_id = apr_pstrndup(comb->res.pool, path, slash - path); comb->priv.root.rev = SVN_STR_TO_REV(slash + 1); /* NOTE: comb->priv.repos_path == NULL */ return FALSE;}static const struct special_defn{ const char *name; /* * COMB is the resource that we are constructing. Any elements that * can be determined from the PATH may be set in COMB. However, further * operations are not allowed (we don't want anything besides a parse * error to occur). * * At a minimum, the parse function must set COMB->res.type and * COMB->priv.repos_path. * * PATH does not contain a leading slash. Given "/root/$svn/xxx/the/path" * as the request URI, the PATH variable will be "the/path" */ int (*parse)(dav_resource_combined *comb, const char *path, const char *label, int use_checked_in); /* The number of subcompenents after the !svn/xxx/... before we reach the actual path within the repository. */ int numcomponents; /* Boolean: are the subcomponents followed by a repos path? */ int has_repos_path; /* The private resource type for the /$svn/xxx/ collection. */ enum dav_svn_private_restype restype;} special_subdirs[] ={ { "ver", dav_svn_parse_version_uri, 1, TRUE, DAV_SVN_RESTYPE_VER_COLLECTION }, { "his", dav_svn_parse_history_uri, 0, FALSE, DAV_SVN_RESTYPE_HIS_COLLECTION }, { "wrk", dav_svn_parse_working_uri, 1, TRUE, DAV_SVN_RESTYPE_WRK_COLLECTION }, { "act", dav_svn_parse_activity_uri, 1, FALSE, DAV_SVN_RESTYPE_ACT_COLLECTION }, { "vcc", dav_svn_parse_vcc_uri, 1, FALSE, DAV_SVN_RESTYPE_VCC_COLLECTION }, { "bc", dav_svn_parse_baseline_coll_uri, 1, TRUE, DAV_SVN_RESTYPE_BC_COLLECTION }, { "bln", dav_svn_parse_baseline_uri, 1, FALSE, DAV_SVN_RESTYPE_BLN_COLLECTION }, { "wbl", dav_svn_parse_wrk_baseline_uri, 2, FALSE, DAV_SVN_RESTYPE_WBL_COLLECTION }, { NULL } /* sentinel */};/* * dav_svn_parse_uri: parse the provided URI into its various bits * * URI will contain a path relative to our configured root URI. It should * not have a leading "/". The root is identified by "". * * On output: *COMB will contain all of the information parsed out of * the URI -- the resource type, activity ID, path, etc. * * Note: this function will only parse the URI. Validation of the pieces, * opening data stores, etc, are not part of this function. * * TRUE is returned if a parsing error occurred. FALSE for success. */static int dav_svn_parse_uri(dav_resource_combined *comb, const char *uri, const char *label, int use_checked_in){ const char *special_uri = comb->priv.repos->special_uri; apr_size_t len1; apr_size_t len2; char ch; len1 = strlen(uri); len2 = strlen(special_uri); if (len1 > len2 && ((ch = uri[len2]) == '/' || ch == '\0') && memcmp(uri, special_uri, len2) == 0) { if (ch == '\0') { /* URI was "/root/!svn". It exists, but has restricted usage. */ comb->res.type = DAV_RESOURCE_TYPE_PRIVATE; comb->priv.restype = DAV_SVN_RESTYPE_ROOT_COLLECTION; } else { const struct special_defn *defn; /* skip past the "!svn/" prefix */ uri += len2 + 1; len1 -= len2 + 1; for (defn = special_subdirs ; defn->name != NULL; ++defn) { apr_size_t len3 = strlen(defn->name); if (len1 >= len3 && memcmp(uri, defn->name, len3) == 0) { if (uri[len3] == '\0') { /* URI was "/root/!svn/XXX". The location exists, but has restricted usage. */ comb->res.type = DAV_RESOURCE_TYPE_PRIVATE; /* store the resource type so that we can PROPFIND on this collection. */ comb->priv.restype = defn->restype; } else if (uri[len3] == '/') { if ((*defn->parse)(comb, uri + len3 + 1, label, use_checked_in)) return TRUE; } else { /* e.g. "/root/!svn/activity" (we just know "act") */ return TRUE; } break; } } /* if completed the loop, then it is an unrecognized subdir */ if (defn->name == NULL) return TRUE; } } else { /* Anything under the root, but not under "!svn". These are all version-controlled resources. */ comb->res.type = DAV_RESOURCE_TYPE_REGULAR; comb->res.versioned = TRUE; /* The location of these resources corresponds directly to the URI, and we keep the leading "/". */ comb->priv.repos_path = comb->priv.uri_path->data; } return FALSE;}static dav_error * dav_svn_prep_regular(dav_resource_combined *comb){ apr_pool_t *pool = comb->res.pool; dav_svn_repos *repos = comb->priv.repos; svn_error_t *serr; dav_error *derr; svn_node_kind_t kind; /* A REGULAR resource might have a specific revision already (e.g. if it is part of a baseline collection). However, if it doesn't, then we will assume that we need the youngest revision. ### other cases besides a BC? */ if (comb->priv.root.rev == SVN_INVALID_REVNUM) { serr = svn_fs_youngest_rev(&comb->priv.root.rev, repos->fs, pool); if (serr != NULL) { return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Could not determine the proper " "revision to access", pool); } } /* get the root of the tree */ serr = svn_fs_revision_root(&comb->priv.root.root, repos->fs, comb->priv.root.rev, pool); if (serr != NULL) { return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Could not open the root of the " "repository", pool); } derr = dav_svn__fs_check_path(&kind, comb->priv.root.root, comb->priv.repos_path, pool); if (derr != NULL) return derr; comb->res.exists = (kind == svn_node_none) ? FALSE : TRUE; comb->res.collection = (kind == svn_node_dir) ? TRUE : FALSE; /* HACK: dav_get_resource_state() is making shortcut assumptions about how to distinguish a null resource from a lock-null resource. This is the only way to get around that problem. Without it, it won't ever detect lock-nulls, and thus 'svn unlock nonexistentURL' will always return 404's. */ if (! comb->res.exists) comb->priv.r->path_info = (char *) ""; return NULL;}static dav_error * dav_svn_prep_version(dav_resource_combined *comb){ svn_error_t *serr; apr_pool_t *pool = comb->res.pool; /* we are accessing the Version Resource by REV/PATH */ /* ### assert: .baselined = TRUE */ /* if we don't have a revision, then assume the youngest */ if (!SVN_IS_VALID_REVNUM(comb->priv.root.rev)) { serr = svn_fs_youngest_rev(&comb->priv.root.rev, comb->priv.repos->fs, pool); if (serr != NULL) { /* ### might not be a baseline */ return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Could not fetch 'youngest' revision " "to enable accessing the latest " "baseline resource.", pool); } } /* ### baselines have no repos_path, and we don't need to open ### a root (yet). we just needed to ensure that we have the proper ### revision number. */ if (!comb->priv.root.root) { serr = svn_fs_revision_root(&comb->priv.root.root, comb->priv.repos->fs, comb->priv.root.rev, pool); if (serr != NULL) { return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Could not open a revision root.", pool); } } /* ### we should probably check that the revision is valid */ comb->res.exists = TRUE; /* Set up the proper URI. Most likely, we arrived here via a VCC, so the URI will be incorrect. Set the canonical form. */ /* ### assuming a baseline */ comb->res.uri = dav_svn_build_uri(comb->priv.repos, DAV_SVN_BUILD_URI_BASELINE, comb->priv.root.rev, NULL, 0 /* add_href */, pool); return NULL;}static dav_error * dav_svn_prep_history(dav_resource_combined *comb){ return NULL;}static dav_error * dav_svn_prep_working(dav_resource_combined *comb){ const char *txn_name = dav_svn_get_txn(comb->priv.repos, comb->priv.root.activity_id); apr_pool_t *pool = comb->res.pool; svn_error_t *serr; dav_error *derr; svn_node_kind_t kind; if (txn_name == NULL) { /* ### HTTP_BAD_REQUEST is probably wrong */ return dav_new_error(pool, HTTP_BAD_REQUEST, 0, "An unknown activity was specified in the URL. " "This is generally caused by a problem in the " "client software."); } comb->priv.root.txn_name = txn_name; /* get the FS transaction, given its name */ serr = svn_fs_open_txn(&comb->priv.root.txn, comb->priv.repos->fs, txn_name, pool); if (serr != NULL) { if (serr->apr_err == SVN_ERR_FS_NO_SUCH_TRANSACTION) { svn_error_clear(serr); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, 0, "An activity was specified and found, but the " "corresponding SVN FS transaction was not " "found."); } return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Could not open the SVN FS transaction " "corresponding to the specified activity.", pool); } if (comb->res.baselined) { /* a Working Baseline */ /* if the transaction exists, then the working resource exists */ comb->res.exists = TRUE; return NULL; } /* Set the txn author if not previously set. Protect against multi-author * commits by verifying authenticated user associated with the current * request is the same as the txn author. * Note that anonymous requests are being excluded as being a change * in author, because the commit may touch areas of the repository * that are anonymous writeable as well as areas that are not. */ if (comb->priv.repos->username) { svn_string_t *current_author; svn_string_t request_author; serr = svn_fs_txn_prop(¤t_author, comb->priv.root.txn, SVN_PROP_REVISION_AUTHOR, pool); if (serr != NULL) { return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Failed to retrieve author of the SVN FS transaction " "corresponding to the specified activity.", pool); } request_author.data = comb->priv.repos->username; request_author.len = strlen(request_author.data); if (!current_author) { serr = svn_fs_change_txn_prop(comb->priv.root.txn, SVN_PROP_REVISION_AUTHOR, &request_author, pool); if (serr != NULL) { return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Failed to set the author of the SVN FS transaction " "corresponding to the specified activity.", pool); } } else if (!svn_string_compare(current_author, &request_author)) { return dav_new_error(pool, HTTP_NOT_IMPLEMENTED, 0, "Multi-author commits not supported."); } } /* get the root of the tree */ serr = svn_fs_txn_root(&comb->priv.root.root, comb->priv.root.txn, pool); if (serr != NULL) { return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, "Could not open the (transaction) root of " "the repository", pool); } derr = dav_svn__fs_check_path(&kind, comb->priv.root.root, comb->priv.repos_path, pool); if (derr != NULL) return derr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -