⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 repos.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 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_fs.h"
#include "svn_repos.h"
#include "svn_config.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_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;
}

/* 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);
  contents = 
    "DB logs lock file, representing locks on the versioned filesystem logs.\n"
    "\n"
    "All log manipulators of the repository's\n"
    "Berkeley DB environment take out exclusive locks on this file\n"
    "to ensure that only one accessor manupulates the logs at the time.\n"
    "\n"
    "You should never have to edit or remove this file.\n";

  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);
    contents = 
      "DB lock file, representing locks on the versioned filesystem.\n"
      "\n"
      "All accessors -- both readers and writers -- of the repository's\n"
      "Berkeley DB environment take out shared locks on this file, and\n"
      "each accessor removes its lock when done.  If and when the DB\n"
      "recovery procedure is run, the recovery code takes out an\n"
      "exclusive lock on this file, so we can be sure no one else is\n"
      "using the DB during the recovery.\n"
      "\n"
      "You should never have to edit or remove this file.\n";
    
  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;
}


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
      "# Here is an example hook script, for a Unix /bin/sh interpreter:"
      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
      "#"
      APR_EOL_STR
      "# The pre-commit hook is invoked before a Subversion txn is"
      APR_EOL_STR
      "# committed.  Subversion runs this hook by invoking a program"
      APR_EOL_STR
      "# (script, executable, binary, etc.) named "
      "'" 
      SVN_REPOS__HOOK_PRE_COMMIT "' (for which"
      APR_EOL_STR
      "# this file is a template), with the following ordered arguments:"
      APR_EOL_STR
      "#"
      APR_EOL_STR
      "#   [1] REPOS-PATH   (the path to this repository)"
      APR_EOL_STR
      "#   [2] TXN-NAME     (the name of the txn about to be committed)"
      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 txn is committed; but"
      APR_EOL_STR
      "# if it exits with failure (non-zero), the txn is aborted, no commit"
      APR_EOL_STR
      "# takes place, and STDERR is returned to the client.   The hook"
      APR_EOL_STR
      "# program can use the 'svnlook' utility to help it examine the txn."
      APR_EOL_STR
      "#"
      APR_EOL_STR
      "# On a Unix system, the normal procedure is to have "
      "'"
      SVN_REPOS__HOOK_PRE_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: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT  ***"
      APR_EOL_STR
      "#   ***  FOR REVISION PROPERTIES (like svn:log or svn:author).   ***"
      APR_EOL_STR
      "#"
      APR_EOL_STR
      "#   This is why we recommend using the read-only 'svnlook' utility."
      APR_EOL_STR
      "#   In the future, Subversion may enforce the rule that pre-commit"
      APR_EOL_STR
      "#   hooks should not modify the versioned data in txns, or else come"
      APR_EOL_STR
      "#   up with a mechanism to make it safe to do so (by informing the"
      APR_EOL_STR
      "#   committing client of the changes).  However, right now neither"
      APR_EOL_STR
      "#   mechanism is implemented, so hook writers just have to be careful."
      APR_EOL_STR
      "#"
      APR_EOL_STR
      "# Note that"
      " '" SVN_REPOS__HOOK_PRE_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_PRE_COMMIT ".bat' or "
      "'" SVN_REPOS__HOOK_PRE_COMMIT ".exe',"
      APR_EOL_STR
      "# but the basic idea is the same."
      APR_EOL_STR
      "#"
      APR_EOL_STR
      "# Here is an example hook script, for a Unix /bin/sh interpreter:"
      APR_EOL_STR
      APR_EOL_STR
      "REPOS=\"$1\""
      APR_EOL_STR
      "TXN=\"$2\""
      APR_EOL_STR
      APR_EOL_STR
      "# Make sure that the log message contains some text."
      APR_EOL_STR
      "SVNLOOK=" SVN_BINARY_DIR "/svnlook"
      APR_EOL_STR
      "$SVNLOOK log -t \"$TXN\" \"$REPOS\" | \\"
      APR_EOL_STR
      "   grep \"[a-zA-Z0-9]\" > /dev/null || exit 1"
      APR_EOL_STR
      APR_EOL_STR
      "# Check that the author of this commit has the rights to perform"
      APR_EOL_STR
      "# the commit on the files and directories being modified."
      APR_EOL_STR
      "commit-access-control.pl \"$REPOS\" \"$TXN\" commit-access-control.cfg "
      "|| exit 1"
      APR_EOL_STR
      APR_EOL_STR
      "# All checks passed, so allow the commit."
      APR_EOL_STR
      "exit 0"
      APR_EOL_STR;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -