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 + -
显示快捷键?