📄 repos.c
字号:
/* * repos.c: mod_dav_svn repository provider functions for Subversion * * ==================================================================== * Copyright (c) 2000-2006 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */#include <httpd.h>#include <http_request.h>#include <http_protocol.h>#include <http_log.h>#include <http_core.h> /* for ap_construct_url */#include <mod_dav.h>#define APR_WANT_STRFUNC#include <apr_want.h>#include <apr_strings.h>#include <apr_hash.h>#include <apr_lib.h>#include "svn_types.h"#include "svn_pools.h"#include "svn_error.h"#include "svn_time.h"#include "svn_fs.h"#include "svn_repos.h"#include "svn_dav.h"#include "svn_sorts.h"#include "svn_version.h"#include "svn_props.h"#include "dav_svn.h"#include "mod_dav_svn.h"struct dav_stream { const dav_resource *res; /* for reading from the FS */ svn_stream_t *rstream; /* for writing to the FS. we use wstream OR the handler/baton. */ svn_stream_t *wstream; svn_txdelta_window_handler_t delta_handler; void *delta_baton;};typedef struct { ap_filter_t *output; apr_pool_t *pool;} dav_svn_diff_ctx_t;typedef struct { dav_resource res; dav_resource_private priv;} dav_resource_combined;/* private context for doing a walk */typedef struct { /* the input walk parameters */ const dav_walk_params *params; /* reused as we walk */ dav_walk_resource wres; /* the current resource */ dav_resource res; /* wres.resource refers here */ dav_resource_private info; /* the info in res */ svn_stringbuf_t *uri; /* the uri within res */ svn_stringbuf_t *repos_path; /* the repos_path within res */} dav_svn_walker_context;/* Helper-wrapper around svn_fs_check_path(), which takes the same arguments. But: if we attempt to stat a path like "file1/file2", then still return 'svn_node_none' to signal nonexistence, rather than a full-blown filesystem error. This allows mod_dav to throw 404 instead of 500. */static dav_error *dav_svn__fs_check_path(svn_node_kind_t *kind, svn_fs_root_t *root, const char *path, apr_pool_t *pool){ svn_error_t *serr; svn_node_kind_t my_kind; serr = svn_fs_check_path(&my_kind, root, path, pool); /* Possibly trap other fs-errors here someday -- errors which may simply indicate the path's nonexistence, rather than a critical problem. */ if (serr && serr->apr_err == SVN_ERR_FS_NOT_DIRECTORY) { svn_error_clear(serr); *kind = svn_node_none; return NULL; } else if (serr) { return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR, apr_psprintf(pool, "Error checking kind of " "path '%s' in repository", path), pool); } *kind = my_kind; return NULL;}static int dav_svn_parse_version_uri(dav_resource_combined *comb, const char *path, const char *label, int use_checked_in){ const char *slash; const char *created_rev_str; /* format: CREATED_REV/REPOS_PATH */ /* ### what to do with LABEL and USE_CHECKED_IN ?? */ comb->res.type = DAV_RESOURCE_TYPE_VERSION; comb->res.versioned = TRUE; slash = ap_strchr_c(path, '/'); if (slash == NULL) { /* http://host.name/repos/$svn/ver/0 This URL form refers to the root path of the repository. */ created_rev_str = apr_pstrndup(comb->res.pool, path, strlen(path)); comb->priv.root.rev = SVN_STR_TO_REV(created_rev_str); comb->priv.repos_path = "/"; } else if (slash == path) { /* the CREATED_REV was missing(?) ### not sure this can happen, though, because it would imply two ### slashes, yet those are cleaned out within get_resource */ return TRUE; } else { apr_size_t len = slash - path; created_rev_str = apr_pstrndup(comb->res.pool, path, len); comb->priv.root.rev = SVN_STR_TO_REV(created_rev_str); comb->priv.repos_path = slash; } /* if the CREATED_REV parsing blew, then propagate it. */ if (comb->priv.root.rev == SVN_INVALID_REVNUM) return TRUE; return FALSE;}static int dav_svn_parse_history_uri(dav_resource_combined *comb, const char *path, const char *label, int use_checked_in){ /* format: ??? */ /* ### what to do with LABEL and USE_CHECKED_IN ?? */ comb->res.type = DAV_RESOURCE_TYPE_HISTORY; /* ### parse path */ comb->priv.repos_path = path; return FALSE;}static int dav_svn_parse_working_uri(dav_resource_combined *comb, const char *path, const char *label, int use_checked_in){ const char *slash; /* format: ACTIVITY_ID/REPOS_PATH */ /* ### what to do with LABEL and USE_CHECKED_IN ?? */ comb->res.type = DAV_RESOURCE_TYPE_WORKING; comb->res.working = TRUE; comb->res.versioned = TRUE; slash = ap_strchr_c(path, '/'); /* This sucker starts with a slash. That's bogus. */ if (slash == path) return TRUE; if (slash == NULL) { /* There's no slash character in our path. Assume it's just an ACTIVITY_ID pointing to the root path. That should be cool. We'll just drop through to the normal case handling below. */ comb->priv.root.activity_id = apr_pstrdup(comb->res.pool, path); comb->priv.repos_path = "/"; } else { comb->priv.root.activity_id = apr_pstrndup(comb->res.pool, path, slash - path); comb->priv.repos_path = slash; } return FALSE;}static int dav_svn_parse_activity_uri(dav_resource_combined *comb, const char *path, const char *label, int use_checked_in){ /* format: ACTIVITY_ID */ /* ### what to do with LABEL and USE_CHECKED_IN ?? */ comb->res.type = DAV_RESOURCE_TYPE_ACTIVITY; comb->priv.root.activity_id = path; return FALSE;}static int dav_svn_parse_vcc_uri(dav_resource_combined *comb, const char *path, const char *label, int use_checked_in){ /* format: "default" (a singleton) */ if (strcmp(path, DAV_SVN_DEFAULT_VCC_NAME) != 0) return TRUE; if (label == NULL && !use_checked_in) { /* Version Controlled Configuration (baseline selector) */ /* ### mod_dav has a proper model for these. technically, they are ### version-controlled resources (REGULAR), but that just monkeys ### up a lot of stuff for us. use a PRIVATE for now. */ comb->res.type = DAV_RESOURCE_TYPE_PRIVATE; /* _REGULAR */ comb->priv.restype = DAV_SVN_RESTYPE_VCC; comb->res.exists = TRUE; comb->res.versioned = TRUE; comb->res.baselined = TRUE; /* NOTE: comb->priv.repos_path == NULL */ } else { /* a specific Version Resource; in this case, a Baseline */ int revnum; if (label != NULL) { revnum = SVN_STR_TO_REV(label); /* assume slash terminates */ if (!SVN_IS_VALID_REVNUM(revnum)) return TRUE; /* ### be nice to get better feedback */ } else /* use_checked_in */ { /* use the DAV:checked-in value of the VCC. this is always the "latest" (or "youngest") revision. */ /* signal dav_svn_prep_version to look it up */ revnum = SVN_INVALID_REVNUM; } comb->res.type = DAV_RESOURCE_TYPE_VERSION; /* exists? need to wait for now */ comb->res.versioned = TRUE; comb->res.baselined = TRUE; /* which baseline (revision tree) to access */ comb->priv.root.rev = revnum; /* NOTE: comb->priv.repos_path == NULL */ /* NOTE: comb->priv.created_rev == SVN_INVALID_REVNUM */ } return FALSE;}static int dav_svn_parse_baseline_coll_uri(dav_resource_combined *comb, const char *path, const char *label, int use_checked_in){ const char *slash; int revnum; /* format: REVISION/REPOS_PATH */ /* ### what to do with LABEL and USE_CHECKED_IN ?? */ slash = ap_strchr_c(path, '/'); if (slash == NULL) slash = "/"; /* they are referring to the root of the BC */ else if (slash == path) return TRUE; /* the REVISION was missing(?) ### not sure this can happen, though, because ### it would imply two slashes, yet those are ### cleaned out within get_resource */ revnum = SVN_STR_TO_REV(path); /* assume slash terminates conversion */ if (!SVN_IS_VALID_REVNUM(revnum)) return TRUE; /* ### be nice to get better feedback */ /* ### mod_dav doesn't have a proper model for these. they are standard ### VCRs, but we need some additional semantics attached to them. ### need to figure out a way to label them as special. */ comb->res.type = DAV_RESOURCE_TYPE_REGULAR; comb->res.versioned = TRUE; comb->priv.root.rev = revnum; comb->priv.repos_path = slash; return FALSE;}static int dav_svn_parse_baseline_uri(dav_resource_combined *comb, const char *path, const char *label, int use_checked_in){ int revnum; /* format: REVISION */ /* ### what to do with LABEL and USE_CHECKED_IN ?? */ revnum = SVN_STR_TO_REV(path); if (!SVN_IS_VALID_REVNUM(revnum)) return TRUE; /* ### be nice to get better feedback */ /* create a Baseline resource (a special Version Resource) */ comb->res.type = DAV_RESOURCE_TYPE_VERSION; /* exists? need to wait for now */ comb->res.versioned = TRUE; comb->res.baselined = TRUE; /* which baseline (revision tree) to access */ comb->priv.root.rev = revnum; /* NOTE: comb->priv.repos_path == NULL */ /* NOTE: comb->priv.created_rev == SVN_INVALID_REVNUM */ return FALSE;}static int dav_svn_parse_wrk_baseline_uri(dav_resource_combined *comb, const char *path, const char *label, int use_checked_in){ const char *slash; /* format: ACTIVITY_ID/REVISION */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -