Alien-SVN
view release on metacpan or search on metacpan
src/subversion/subversion/libsvn_repos/repos.c view on Meta::CPAN
/* Set *REPOS_P to a repository at PATH which has been opened.
See lock_repos() above regarding EXCLUSIVE and NONBLOCKING.
OPEN_FS indicates whether the Subversion filesystem should be opened,
the handle being placed into repos->fs.
Do all allocation in POOL. */
static svn_error_t *
get_repos(svn_repos_t **repos_p,
const char *path,
svn_boolean_t exclusive,
svn_boolean_t nonblocking,
svn_boolean_t open_fs,
apr_hash_t *fs_config,
apr_pool_t *pool)
{
svn_repos_t *repos;
/* Allocate a repository object. */
repos = create_svn_repos_t(path, pool);
/* Verify the validity of our repository format. */
SVN_ERR(check_repos_format(repos, pool));
/* Discover the FS type. */
SVN_ERR(svn_fs_type(&repos->fs_type, repos->db_path, pool));
/* Lock if needed. */
SVN_ERR(lock_repos(repos, exclusive, nonblocking, pool));
/* Open up the filesystem only after obtaining the lock. */
if (open_fs)
SVN_ERR(svn_fs_open(&repos->fs, repos->db_path, fs_config, pool));
#ifdef SVN_DEBUG_CRASH_AT_REPOS_OPEN
/* If $PATH/config/debug-abort exists, crash the server here.
This debugging feature can be used to test client recovery
when the server crashes.
See: Issue #4274 */
{
svn_node_kind_t kind;
svn_error_t *err = svn_io_check_path(
svn_dirent_join(repos->conf_path, "debug-abort", pool),
&kind, pool);
svn_error_clear(err);
if (!err && kind == svn_node_file)
SVN_ERR_MALFUNCTION_NO_RETURN();
}
#endif /* SVN_DEBUG_CRASH_AT_REPOS_OPEN */
*repos_p = repos;
return SVN_NO_ERROR;
}
const char *
svn_repos_find_root_path(const char *path,
apr_pool_t *pool)
{
const char *candidate = path;
const char *decoded;
svn_error_t *err;
while (1)
{
/* Try to decode the path, so we don't fail if it contains characters
that aren't supported by the OS filesystem. The subversion fs
isn't restricted by the OS filesystem character set. */
err = svn_path_cstring_from_utf8(&decoded, candidate, pool);
if (!err && check_repos_path(candidate, pool))
break;
svn_error_clear(err);
if (svn_path_is_empty(candidate) ||
svn_dirent_is_root(candidate, strlen(candidate)))
return NULL;
candidate = svn_dirent_dirname(candidate, pool);
}
return candidate;
}
svn_error_t *
svn_repos_open2(svn_repos_t **repos_p,
const char *path,
apr_hash_t *fs_config,
apr_pool_t *pool)
{
/* Fetch a repository object initialized with a shared read/write
lock on the database. */
return get_repos(repos_p, path, FALSE, FALSE, TRUE, fs_config, pool);
}
svn_error_t *
svn_repos_upgrade2(const char *path,
svn_boolean_t nonblocking,
svn_repos_notify_func_t notify_func,
void *notify_baton,
apr_pool_t *pool)
{
svn_repos_t *repos;
const char *format_path;
int format;
apr_pool_t *subpool = svn_pool_create(pool);
/* Fetch a repository object; for the Berkeley DB backend, it is
initialized with an EXCLUSIVE lock on the database. This will at
least prevent others from trying to read or write to it while we
run recovery. (Other backends should do their own locking; see
lock_repos.) */
SVN_ERR(get_repos(&repos, path, TRUE, nonblocking, FALSE, NULL, subpool));
if (notify_func)
{
/* We notify *twice* here, because there are two different logistical
actions occuring. */
svn_repos_notify_t *notify = svn_repos_notify_create(
svn_repos_notify_mutex_acquired, subpool);
notify_func(notify_baton, notify, subpool);
notify->action = svn_repos_notify_upgrade_start;
notify_func(notify_baton, notify, subpool);
}
/* Try to overwrite with its own contents. We do this only to
( run in 1.105 second using v1.01-cache-2.11-cpan-df04353d9ac )