📄 repos.c
字号:
/* repos.c : repository creation; shared and exclusive repository locking * * ==================================================================== * Copyright (c) 2000-2004 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 <assert.h>#include <apr_pools.h>#include <apr_file_io.h>#include "svn_pools.h"#include "svn_error.h"#include "svn_path.h"#include "svn_utf.h"#include "svn_time.h"#include "svn_fs.h"#include "svn_repos.h"#include "svn_private_config.h" /* for SVN_TEMPLATE_ROOT_DIR */#include "repos.h"/* Path accessor functions. */const char *svn_repos_path(svn_repos_t *repos, apr_pool_t *pool){ return apr_pstrdup(pool, repos->path);}const char *svn_repos_db_env(svn_repos_t *repos, apr_pool_t *pool){ return apr_pstrdup(pool, repos->db_path);}const char *svn_repos_conf_dir(svn_repos_t *repos, apr_pool_t *pool){ return apr_pstrdup(pool, repos->conf_path);}const char *svn_repos_svnserve_conf(svn_repos_t *repos, apr_pool_t *pool){ return svn_path_join(repos->conf_path, SVN_REPOS__CONF_SVNSERVE_CONF, pool);}const char *svn_repos_lock_dir(svn_repos_t *repos, apr_pool_t *pool){ return apr_pstrdup(pool, repos->lock_path);}const char *svn_repos_db_lockfile(svn_repos_t *repos, apr_pool_t *pool){ return svn_path_join(repos->lock_path, SVN_REPOS__DB_LOCKFILE, pool);}const char *svn_repos_db_logs_lockfile(svn_repos_t *repos, apr_pool_t *pool){ return svn_path_join(repos->lock_path, SVN_REPOS__DB_LOGS_LOCKFILE, pool);}const char *svn_repos_hook_dir(svn_repos_t *repos, apr_pool_t *pool){ return apr_pstrdup(pool, repos->hook_path);}const char *svn_repos_start_commit_hook(svn_repos_t *repos, apr_pool_t *pool){ return svn_path_join(repos->hook_path, SVN_REPOS__HOOK_START_COMMIT, pool);}const char *svn_repos_pre_commit_hook(svn_repos_t *repos, apr_pool_t *pool){ return svn_path_join(repos->hook_path, SVN_REPOS__HOOK_PRE_COMMIT, pool);}const char *svn_repos_pre_lock_hook(svn_repos_t *repos, apr_pool_t *pool){ return svn_path_join(repos->hook_path, SVN_REPOS__HOOK_PRE_LOCK, pool);}const char *svn_repos_pre_unlock_hook(svn_repos_t *repos, apr_pool_t *pool){ return svn_path_join(repos->hook_path, SVN_REPOS__HOOK_PRE_UNLOCK, pool);}const char *svn_repos_post_lock_hook(svn_repos_t *repos, apr_pool_t *pool){ return svn_path_join(repos->hook_path, SVN_REPOS__HOOK_POST_LOCK, pool);}const char *svn_repos_post_unlock_hook(svn_repos_t *repos, apr_pool_t *pool){ return svn_path_join(repos->hook_path, SVN_REPOS__HOOK_POST_UNLOCK, pool);}const char *svn_repos_post_commit_hook(svn_repos_t *repos, apr_pool_t *pool){ return svn_path_join(repos->hook_path, SVN_REPOS__HOOK_POST_COMMIT, pool);}const char *svn_repos_pre_revprop_change_hook(svn_repos_t *repos, apr_pool_t *pool){ return svn_path_join(repos->hook_path, SVN_REPOS__HOOK_PRE_REVPROP_CHANGE, pool);}const char *svn_repos_post_revprop_change_hook(svn_repos_t *repos, apr_pool_t *pool){ return svn_path_join(repos->hook_path, SVN_REPOS__HOOK_POST_REVPROP_CHANGE, pool);}static svn_error_t *create_repos_dir(const char *path, apr_pool_t *pool){ svn_error_t *err; err = svn_io_dir_make(path, APR_OS_DEFAULT, pool); if (err && (APR_STATUS_IS_EEXIST(err->apr_err))) { svn_boolean_t is_empty; svn_error_clear(err); SVN_ERR(svn_io_dir_empty(&is_empty, path, pool)); if (is_empty) err = NULL; else err = svn_error_createf(SVN_ERR_DIR_NOT_EMPTY, 0, _("'%s' exists and is non-empty"), path); } return err;}static const char * bdb_lock_file_contents = "DB lock file, representing locks on the versioned filesystem." APR_EOL_STR APR_EOL_STR "All accessors -- both readers and writers -- of the repository's" APR_EOL_STR "Berkeley DB environment take out shared locks on this file, and" APR_EOL_STR "each accessor removes its lock when done. If and when the DB" APR_EOL_STR "recovery procedure is run, the recovery code takes out an" APR_EOL_STR "exclusive lock on this file, so we can be sure no one else is" APR_EOL_STR "using the DB during the recovery." APR_EOL_STR APR_EOL_STR "You should never have to edit or remove this file." APR_EOL_STR;static const char * bdb_logs_lock_file_contents = "DB logs lock file, representing locks on the versioned filesystem logs." APR_EOL_STR APR_EOL_STR "All log manipulators of the repository's Berkeley DB environment" APR_EOL_STR "take out exclusive locks on this file to ensure that only one" APR_EOL_STR "accessor manipulates the logs at a time." APR_EOL_STR APR_EOL_STR "You should never have to edit or remove this file." APR_EOL_STR;static const char * pre12_compat_unneeded_file_contents = "This file is not used by Subversion 1.3.x or later." APR_EOL_STR "However, its existence is required for compatibility with" APR_EOL_STR "Subversion 1.2.x or earlier." APR_EOL_STR;/* Create the DB logs lockfile. */static svn_error_t *create_db_logs_lock(svn_repos_t *repos, apr_pool_t *pool) { const char *contents; const char *lockfile_path; lockfile_path = svn_repos_db_logs_lockfile(repos, pool); if (strcmp(repos->fs_type, SVN_FS_TYPE_BDB) == 0) contents = bdb_logs_lock_file_contents; else contents = pre12_compat_unneeded_file_contents; SVN_ERR_W(svn_io_file_create(lockfile_path, contents, pool), _("Creating db logs lock file")); return SVN_NO_ERROR;}/* Create the DB lockfile. */static svn_error_t *create_db_lock(svn_repos_t *repos, apr_pool_t *pool) { const char *contents; const char *lockfile_path; lockfile_path = svn_repos_db_lockfile(repos, pool); if (strcmp(repos->fs_type, SVN_FS_TYPE_BDB) == 0) contents = bdb_lock_file_contents; else contents = pre12_compat_unneeded_file_contents; SVN_ERR_W(svn_io_file_create(lockfile_path, contents, pool), _("Creating db lock file")); return SVN_NO_ERROR;}static svn_error_t *create_locks(svn_repos_t *repos, apr_pool_t *pool){ /* Create the locks directory. */ SVN_ERR_W(create_repos_dir(repos->lock_path, pool), _("Creating lock dir")); SVN_ERR(create_db_lock(repos, pool)); SVN_ERR(create_db_logs_lock(repos, pool)); return SVN_NO_ERROR;}#define HOOKS_ENVIRONMENT_TEXT \ "# The hook program typically does not inherit the environment of" \ APR_EOL_STR \ "# its parent process. For example, a common problem is for the" \ APR_EOL_STR \ "# PATH environment variable to not be set to its usual value, so" \ APR_EOL_STR \ "# that subprograms fail to launch unless invoked via absolute path." \ APR_EOL_STR \ "# If you're having unexpected problems with a hook program, the" \ APR_EOL_STR \ "# culprit may be unusual (or missing) environment variables." \ APR_EOL_STR#define PREWRITTEN_HOOKS_TEXT \ "# For more examples and pre-written hooks, see those in" \ APR_EOL_STR \ "# the Subversion repository at" \ APR_EOL_STR \ "# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and" \ APR_EOL_STR \ "# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/" \ APR_EOL_STR \static svn_error_t *create_hooks(svn_repos_t *repos, apr_pool_t *pool){ const char *this_path, *contents; /* Create the hook directory. */ SVN_ERR_W(create_repos_dir(repos->hook_path, pool), _("Creating hook directory")); /*** Write a default template for each standard hook file. */ /* Start-commit hook. */ { this_path = apr_psprintf(pool, "%s%s", svn_repos_start_commit_hook(repos, pool), SVN_REPOS__HOOK_DESC_EXT); contents = "#!/bin/sh" APR_EOL_STR APR_EOL_STR "# START-COMMIT HOOK" APR_EOL_STR "#" APR_EOL_STR "# The start-commit hook is invoked before a Subversion txn is created" APR_EOL_STR "# in the process of doing a commit. Subversion runs this hook" APR_EOL_STR "# by invoking a program (script, executable, binary, etc.) named" APR_EOL_STR "# '" SVN_REPOS__HOOK_START_COMMIT "' (for which this file is a template)" APR_EOL_STR "# with the following ordered arguments:" APR_EOL_STR "#" APR_EOL_STR "# [1] REPOS-PATH (the path to this repository)" APR_EOL_STR "# [2] USER (the authenticated user attempting to commit)" APR_EOL_STR "#" APR_EOL_STR "# The default working directory for the invocation is undefined, so" APR_EOL_STR "# the program should set one explicitly if it cares." APR_EOL_STR "#" APR_EOL_STR "# If the hook program exits with success, the commit continues; but" APR_EOL_STR "# if it exits with failure (non-zero), the commit is stopped before" APR_EOL_STR "# a Subversion txn is created, and STDERR is returned to the client." APR_EOL_STR "#" APR_EOL_STR "# On a Unix system, the normal procedure is to have " "'" SVN_REPOS__HOOK_START_COMMIT "'" APR_EOL_STR "# invoke other programs to do the real work, though it may do the" APR_EOL_STR "# work itself too." APR_EOL_STR "#" APR_EOL_STR "# Note that" " '" SVN_REPOS__HOOK_START_COMMIT "' " "must be executable by the user(s) who will" APR_EOL_STR "# invoke it (typically the user httpd runs as), and that user must" APR_EOL_STR "# have filesystem-level permission to access the repository." APR_EOL_STR "#" APR_EOL_STR "# On a Windows system, you should name the hook program" APR_EOL_STR "# '" SVN_REPOS__HOOK_START_COMMIT ".bat' or " "'" SVN_REPOS__HOOK_START_COMMIT ".exe'," APR_EOL_STR "# but the basic idea is the same." APR_EOL_STR "# " APR_EOL_STR HOOKS_ENVIRONMENT_TEXT "# " APR_EOL_STR "# Here is an example hook script, for a Unix /bin/sh interpreter." APR_EOL_STR PREWRITTEN_HOOKS_TEXT APR_EOL_STR APR_EOL_STR "REPOS=\"$1\"" APR_EOL_STR "USER=\"$2\"" APR_EOL_STR APR_EOL_STR "commit-allower.pl --repository \"$REPOS\" --user \"$USER\" || exit 1" APR_EOL_STR "special-auth-check.py --user \"$USER\" --auth-level 3 || exit 1" APR_EOL_STR APR_EOL_STR "# All checks passed, so allow the commit." APR_EOL_STR "exit 0" APR_EOL_STR; SVN_ERR_W(svn_io_file_create(this_path, contents, pool), _("Creating start-commit hook")); } /* end start-commit hook */ /* Pre-commit hook. */ { this_path = apr_psprintf(pool, "%s%s", svn_repos_pre_commit_hook(repos, pool), SVN_REPOS__HOOK_DESC_EXT); contents = "#!/bin/sh" APR_EOL_STR APR_EOL_STR "# PRE-COMMIT HOOK" APR_EOL_STR "#"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -