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

📄 version.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * version.c: mod_dav_svn versioning provider functions for Subversion
 *
 * ====================================================================
 * 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 <httpd.h>
#include <http_log.h>
#include <mod_dav.h>
#include <apr_tables.h>
#include <apr_uuid.h>

#include "svn_fs.h"
#include "svn_xml.h"
#include "svn_repos.h"
#include "svn_dav.h"
#include "svn_time.h"
#include "svn_pools.h"
#include "svn_dav.h"

#include "dav_svn.h"


/* ### should move these report names to a public header to share with
   ### the client (and third parties). */
static const dav_report_elem avail_reports[] = {
  { SVN_XML_NAMESPACE, "update-report" },
  { SVN_XML_NAMESPACE, "log-report" },
  { NULL },
};

/* declare these static functions early, so we can use them anywhere. */
static dav_error *dav_svn_make_activity(dav_resource *resource);


/* Helper: attach an auto-generated svn:log property to a txn within
   an auto-checked-out working resource. */
static dav_error *set_auto_log_message(dav_resource *resource)
{
  const char *logmsg;
  svn_string_t *logval;
  svn_error_t *serr;

  if (! (resource->type == DAV_RESOURCE_TYPE_WORKING
         && resource->info->auto_checked_out))
    return dav_new_error(resource->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
                         "set_auto_log_message called on invalid resource.");
  
  logmsg = apr_psprintf(resource->pool, 
                        "Autoversioning commit:  a non-deltaV client made "
                        "a change to\n%s", resource->info->repos_path);

  logval = svn_string_create(logmsg, resource->pool);

  serr = svn_repos_fs_change_txn_prop(resource->info->root.txn,
                                      SVN_PROP_REVISION_LOG, logval,
                                      resource->pool);
  if (serr)
    return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                               "Error setting auto-log-message on "
                               "auto-checked-out resource's transaction.",
                               resource->pool);
  return NULL;
}

static dav_error *open_txn(svn_fs_txn_t **ptxn, svn_fs_t *fs,
                           const char *txn_name, apr_pool_t *pool)
{
  svn_error_t *serr;

  serr = svn_fs_open_txn(ptxn, fs, txn_name, pool);
  if (serr != NULL)
    {
      if (serr->apr_err == SVN_ERR_FS_NO_SUCH_TRANSACTION)
        {
          /* ### correct HTTP error? */
          return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                     "The transaction specified by the "
                                     "activity does not exist",
                                     pool);
        }

      /* ### correct HTTP error? */
      return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                 "There was a problem opening the "
                                 "transaction specified by this "
                                 "activity.",
                                 pool);
    }

  return NULL;
}

static void dav_svn_get_vsn_options(apr_pool_t *p, apr_text_header *phdr)
{
  /* Note: we append pieces with care for Web Folders's 63-char limit
     on the DAV: header */

  apr_text_append(p, phdr,
                  "version-control,checkout,working-resource");
  apr_text_append(p, phdr,
                  "merge,baseline,activity,version-controlled-collection");

  /* ### fork-control? */
}

static dav_error *dav_svn_get_option(const dav_resource *resource,
                                     const apr_xml_elem *elem,
                                     apr_text_header *option)
{
  /* ### DAV:version-history-collection-set */

  if (elem->ns == APR_XML_NS_DAV_ID)
    {
      if (strcmp(elem->name, "activity-collection-set") == 0)
        {
          apr_text_append(resource->pool, option,
                          "<D:activity-collection-set>");
          apr_text_append(resource->pool, option,
                          dav_svn_build_uri(resource->info->repos,
                                            DAV_SVN_BUILD_URI_ACT_COLLECTION,
                                            SVN_INVALID_REVNUM, NULL,
                                            1 /* add_href */, resource->pool));
          apr_text_append(resource->pool, option,
                          "</D:activity-collection-set>");
        }
    }

  return NULL;
}

static int dav_svn_versionable(const dav_resource *resource)
{
  return 0;
}

static dav_auto_version dav_svn_auto_versionable(const dav_resource *resource)
{
  /* The svn client attempts to proppatch a baseline when changing
     unversioned revision props.  Thus we allow baselines to be
     "auto-checked-out" by mod_dav.  See issue #916. */
  if (resource->type == DAV_RESOURCE_TYPE_VERSION
      && resource->baselined)
    return DAV_AUTO_VERSION_ALWAYS;

  /* No other autoversioning is allowed unless the SVNAutoversioning
     directive is used. */
  if (resource->info->repos->autoversioning)
    {
      /* This allows a straight-out PUT on a public file or collection
         VCR.  mod_dav's auto-versioning subsystem will check to see if
         it's possible to auto-checkout a regular resource. */
      if (resource->type == DAV_RESOURCE_TYPE_REGULAR)
        return DAV_AUTO_VERSION_ALWAYS;

      /* mod_dav's auto-versioning subsystem will also check to see if
         it's possible to auto-checkin a working resource that was
         auto-checked-out.  We *only* allow auto-versioning on a working
         resource if it was auto-checked-out. */
      if (resource->type == DAV_RESOURCE_TYPE_WORKING
          && resource->info->auto_checked_out)
        return DAV_AUTO_VERSION_ALWAYS;
    }

  /* Default:  whatever it is, assume it's not auto-versionable */
  return DAV_AUTO_VERSION_NEVER;
}

static dav_error *dav_svn_vsn_control(dav_resource *resource,
                                      const char *target)
{
  /* All mod_dav_svn resources are versioned objects;  so it doesn't
     make sense to call vsn_control on a resource that exists . */
  if (resource->exists)
    return dav_new_error(resource->pool, HTTP_BAD_REQUEST, 0,
                         "vsn_control called on already-versioned resource.");

  /* Only allow a NULL target, which means an create an 'empty' VCR. */
  if (target != NULL)
    return dav_new_error_tag(resource->pool, HTTP_NOT_IMPLEMENTED,
                             SVN_ERR_UNSUPPORTED_FEATURE,
                             "vsn_control called with non-null target.",
                             SVN_DAV_ERROR_NAMESPACE,
                             SVN_DAV_ERROR_TAG);

  /* This is kind of silly.  The docstring for this callback says it's
     supposed to "put a resource under version control".  But in
     Subversion, all REGULAR resources (bc's or public URIs) are
     already under version control. So we don't need to do a thing to
     the resource, just return. */
  return NULL;
}

dav_error *dav_svn_checkout(dav_resource *resource,
                            int auto_checkout,
                            int is_unreserved, int is_fork_ok,
                            int create_activity,
                            apr_array_header_t *activities,
                            dav_resource **working_resource)
{
  const char *txn_name;
  svn_error_t *serr;
  dav_error *derr;
  dav_svn_uri_info parse;

  /* Auto-Versioning Stuff */
  if (auto_checkout)
    {
      dav_resource *res; /* ignored */
      apr_uuid_t uuid;
      char uuid_buf[APR_UUID_FORMATTED_LENGTH + 1];

      /* Baselines can be auto-checked-out -- grudgingly -- so we can
         allow clients to proppatch unversioned rev props.  See issue
         #916. */
      if ((resource->type == DAV_RESOURCE_TYPE_VERSION)
          && resource->baselined)
        /* ### We're violating deltaV big time here, by allowing a
           dav_auto_checkout() on something that mod_dav assumes is a
           VCR, not a VR.  Anyway, mod_dav thinks we're checking out the
           resource 'in place', so that no working resource is returned.
           (It passes NULL as **working_resource.)  */
        return NULL;

      if (resource->type != DAV_RESOURCE_TYPE_REGULAR)
        return dav_new_error_tag(resource->pool, HTTP_METHOD_NOT_ALLOWED,
                                 SVN_ERR_UNSUPPORTED_FEATURE,
                                 "auto-checkout attempted on non-regular "
                                 "version-controlled resource.",
                                 SVN_DAV_ERROR_NAMESPACE,
                                 SVN_DAV_ERROR_TAG);

      if (resource->baselined)
        return dav_new_error_tag(resource->pool, HTTP_METHOD_NOT_ALLOWED,
                                 SVN_ERR_UNSUPPORTED_FEATURE,
                                 "auto-checkout attempted on baseline "
                                 "collection, which is not supported.",
                                 SVN_DAV_ERROR_NAMESPACE,
                                 SVN_DAV_ERROR_TAG);

      /* Come up with a unique activity name, put it in the resource. */
      apr_uuid_get(&uuid);
      apr_uuid_format(uuid_buf, &uuid);
      resource->info->root.activity_id = uuid_buf;

      /* Remember that this resource was auto-checked-out, so that
         dav_svn_auto_versionable allows us to do an auto-checkin and
         dav_svn_can_be_activity will allow this resource to be an
         activity. */
      resource->info->auto_checked_out = TRUE;

      /* Create a txn based on youngest rev, and create an associated
         activity id in the activity database. */
      derr = dav_svn_make_activity(resource);
      if (derr)
        return derr;
      
      /* Tweak the VCR in-place, making it into a WR.  (Ignore the
         NULL return value.) */
      res = dav_svn_create_working_resource(resource, uuid_buf, 
                                            resource->info->root.txn_name,
                                            TRUE /* tweak in place */);

      /* Finally, be sure to open the txn and txn_root in the
         resource.  Normally we only get a PUT on a WR uri, and
         prep_working() opens the txn automatically.  We need to make
         sure this WR is in the exact same state, ready for a PUT. */
      derr = open_txn(&resource->info->root.txn, resource->info->repos->fs,
                      resource->info->root.txn_name, resource->pool);
      if (derr)
        return derr;

      serr = svn_fs_txn_root(&resource->info->root.root,
                             resource->info->root.txn, resource->pool);
      if (serr != NULL)
        return dav_svn_convert_err(serr, HTTP_INTERNAL_SERVER_ERROR,
                                   "Could not open the (transaction) root "
                                   "of the repository",
                                   resource->pool);
        
      return NULL;
    }
  /* end of Auto-Versioning Stuff */

  if (resource->type != DAV_RESOURCE_TYPE_VERSION)
    {
      return dav_new_error_tag(resource->pool, HTTP_METHOD_NOT_ALLOWED,
                               SVN_ERR_UNSUPPORTED_FEATURE,
                               "CHECKOUT can only be performed on a version "
                               "resource [at this time].",
                               SVN_DAV_ERROR_NAMESPACE,
                               SVN_DAV_ERROR_TAG);
    }
  if (create_activity)
    {

⌨️ 快捷键说明

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