ra_plugin.c
来自「linux subdivision ying gai ke yi le ba」· C语言 代码 · 共 983 行 · 第 1/3 页
C
983 行
/*
* ra_plugin.c : the main RA module for local repository access
*
* ====================================================================
* 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 "ra_local.h"
#include "svn_ra.h"
#include "svn_fs.h"
#include "svn_delta.h"
#include "svn_repos.h"
#include "svn_pools.h"
#include "svn_time.h"
#include "svn_private_config.h"
#define APR_WANT_STRFUNC
#include <apr_want.h>
#include <assert.h>
/*----------------------------------------------------------------*/
/* The reporter vtable needed by do_update() */
typedef struct reporter_baton_t
{
svn_ra_local__session_baton_t *session;
void *report_baton;
} reporter_baton_t;
static void *
make_reporter_baton (svn_ra_local__session_baton_t *session,
void *report_baton,
apr_pool_t *pool)
{
reporter_baton_t *rbaton = apr_palloc (pool, sizeof (*rbaton));
rbaton->session = session;
rbaton->report_baton = report_baton;
return rbaton;
}
static svn_error_t *
reporter_set_path (void *reporter_baton,
const char *path,
svn_revnum_t revision,
svn_boolean_t start_empty,
apr_pool_t *pool)
{
reporter_baton_t *rbaton = reporter_baton;
return svn_repos_set_path (rbaton->report_baton, path,
revision, start_empty, pool);
}
static svn_error_t *
reporter_delete_path (void *reporter_baton,
const char *path,
apr_pool_t *pool)
{
reporter_baton_t *rbaton = reporter_baton;
return svn_repos_delete_path (rbaton->report_baton, path, pool);
}
static svn_error_t *
reporter_link_path (void *reporter_baton,
const char *path,
const char *url,
svn_revnum_t revision,
svn_boolean_t start_empty,
apr_pool_t *pool)
{
reporter_baton_t *rbaton = reporter_baton;
const char *fs_path = NULL;
const char *repos_url_decoded;
int repos_url_len;
url = svn_path_uri_decode(url, pool);
repos_url_decoded = svn_path_uri_decode(rbaton->session->repos_url, pool);
repos_url_len = strlen(repos_url_decoded);
if (strncmp(url, repos_url_decoded, repos_url_len) != 0)
return svn_error_createf (SVN_ERR_RA_ILLEGAL_URL, NULL,
_("'%s'\n"
"is not the same repository as\n"
"'%s'"), url, rbaton->session->repos_url);
fs_path = url + repos_url_len;
return svn_repos_link_path (rbaton->report_baton, path,
fs_path, revision, start_empty, pool);
}
static svn_error_t *
reporter_finish_report (void *reporter_baton,
apr_pool_t *pool)
{
reporter_baton_t *rbaton = reporter_baton;
return svn_repos_finish_report (rbaton->report_baton, pool);
}
static svn_error_t *
reporter_abort_report (void *reporter_baton,
apr_pool_t *pool)
{
reporter_baton_t *rbaton = reporter_baton;
return svn_repos_abort_report (rbaton->report_baton, pool);
}
static const svn_ra_reporter_t ra_local_reporter =
{
reporter_set_path,
reporter_delete_path,
reporter_link_path,
reporter_finish_report,
reporter_abort_report
};
static svn_error_t *
svn_ra_local__get_file_revs (void *session_baton,
const char *path,
svn_revnum_t start,
svn_revnum_t end,
svn_ra_file_rev_handler_t handler,
void *handler_baton,
apr_pool_t *pool)
{
svn_ra_local__session_baton_t *sbaton = session_baton;
const char *abs_path = sbaton->fs_path;
/* Concatenate paths */
abs_path = svn_path_join (abs_path, path, pool);
return svn_repos_get_file_revs (sbaton->repos, abs_path, start, end, NULL,
NULL, handler, handler_baton, pool);
}
static svn_error_t *
get_username (svn_ra_local__session_baton_t *session,
apr_pool_t *pool)
{
svn_auth_iterstate_t *iterstate;
/* If we've already found the username don't ask for it again */
if (session->username)
return SVN_NO_ERROR;
/* Get a username somehow, so we have some svn:author property to
attach to a commit. */
if (! session->callbacks->auth_baton)
{
session->username = "";
}
else
{
void *creds;
svn_auth_cred_username_t *username_creds;
SVN_ERR (svn_auth_first_credentials (&creds, &iterstate,
SVN_AUTH_CRED_USERNAME,
session->uuid, /* realmstring */
session->callbacks->auth_baton,
pool));
/* No point in calling next_creds(), since that assumes that the
first_creds() somehow failed to authenticate. But there's no
challenge going on, so we use whatever creds we get back on
the first try. */
username_creds = creds;
if (username_creds && username_creds->username)
{
session->username = apr_pstrdup (pool, username_creds->username);
svn_error_clear (svn_auth_save_credentials (iterstate, pool));
}
else
session->username = "";
}
return SVN_NO_ERROR;
}
/*----------------------------------------------------------------*/
/** The RA plugin routines **/
static svn_error_t *
svn_ra_local__open (void **session_baton,
const char *repos_URL,
const svn_ra_callbacks_t *callbacks,
void *callback_baton,
apr_hash_t *config,
apr_pool_t *pool)
{
svn_ra_local__session_baton_t *session;
/* Allocate and stash the session_baton args we have already. */
session = apr_pcalloc (pool, sizeof(*session));
session->pool = pool;
session->repository_URL = repos_URL;
/* Look through the URL, figure out which part points to the
repository, and which part is the path *within* the
repository. */
SVN_ERR_W (svn_ra_local__split_URL (&(session->repos),
&(session->repos_url),
&(session->fs_path),
session->repository_URL,
session->pool),
_("Unable to open an ra_local session to URL"));
/* Cache the filesystem object from the repos here for
convenience. */
session->fs = svn_repos_fs (session->repos);
/* Cache the repository UUID as well */
SVN_ERR (svn_fs_get_uuid (session->fs, &session->uuid, session->pool));
/* Stuff the callbacks/baton here. */
session->callbacks = callbacks;
session->callback_baton = callback_baton;
/* Be sure username is NULL so we know to look it up / ask for it */
session->username = NULL;
*session_baton = session;
return SVN_NO_ERROR;
}
static svn_error_t *
svn_ra_local__get_latest_revnum (void *session_baton,
svn_revnum_t *latest_revnum,
apr_pool_t *pool)
{
svn_ra_local__session_baton_t *baton =
(svn_ra_local__session_baton_t *) session_baton;
SVN_ERR (svn_fs_youngest_rev (latest_revnum, baton->fs, pool));
return SVN_NO_ERROR;
}
static svn_error_t *
svn_ra_local__get_dated_revision (void *session_baton,
svn_revnum_t *revision,
apr_time_t tm,
apr_pool_t *pool)
{
svn_ra_local__session_baton_t *baton =
(svn_ra_local__session_baton_t *) session_baton;
SVN_ERR (svn_repos_dated_revision (revision, baton->repos, tm, pool));
return SVN_NO_ERROR;
}
static svn_error_t *
svn_ra_local__change_rev_prop (void *session_baton,
svn_revnum_t rev,
const char *name,
const svn_string_t *value,
apr_pool_t *pool)
{
svn_ra_local__session_baton_t *baton =
(svn_ra_local__session_baton_t *) session_baton;
SVN_ERR (get_username (baton, pool));
SVN_ERR (svn_repos_fs_change_rev_prop2 (baton->repos, rev, baton->username,
name, value, NULL, NULL, pool));
return SVN_NO_ERROR;
}
static svn_error_t *
svn_ra_local__get_uuid (void *session_baton,
const char **uuid,
apr_pool_t *pool)
{
svn_ra_local__session_baton_t *baton =
(svn_ra_local__session_baton_t *) session_baton;
*uuid = baton->uuid;
return SVN_NO_ERROR;
}
static svn_error_t *
svn_ra_local__get_repos_root (void *session_baton,
const char **url,
apr_pool_t *pool)
{
svn_ra_local__session_baton_t *baton =
(svn_ra_local__session_baton_t *) session_baton;
*url = baton->repos_url;
return SVN_NO_ERROR;
}
static svn_error_t *
svn_ra_local__rev_proplist (void *session_baton,
svn_revnum_t rev,
apr_hash_t **props,
apr_pool_t *pool)
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?