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

📄 commit.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * commit.c :  routines for committing changes to the server * * ==================================================================== * 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 <apr_pools.h>#include <apr_hash.h>#include <apr_uuid.h>#define APR_WANT_STDIO#define APR_WANT_STRFUNC#include <apr_want.h>#include <stdlib.h>     /* for free() */#include <assert.h>#include <ne_socket.h>#include <ne_request.h>#include <ne_props.h>#include <ne_basic.h>#include "svn_pools.h"#include "svn_error.h"#include "svn_delta.h"#include "svn_io.h"#include "svn_ra.h"#include "../libsvn_ra/ra_loader.h"#include "svn_path.h"#include "svn_xml.h"#include "svn_dav.h"#include "svn_props.h"#include "svn_private_config.h"#include "ra_dav.h"/*** version_rsrc_t: identify the relevant pieces of a resource on the server**** REVISION is the resource's revision, or SVN_INVALID_REVNUM if it is** new or is the HEAD.**** URL refers to the public/viewable/original resource.** VSN_URL refers to the version resource that we stored locally** WR_URL refers to a working resource for this resource**** Note that VSN_URL is NULL if this resource has just been added, and** WR_URL can be NULL if the resource has not (yet) been checked out.**** LOCAL_PATH is relative to the root of the commit. It will be used** for the get_func, push_func, and close_func callbacks.*/typedef struct{  svn_revnum_t revision;  const char *url;  const char *vsn_url;  const char *wr_url;  const char *local_path;  apr_pool_t *pool; /* pool in which this resource is allocated. */} version_rsrc_t;/* Context for parsing <D:error> bodies, used when we call ne_copy(). */struct copy_baton{  /* An indication of whether we're currently processing a COPY request   * or not.   */  svn_boolean_t making_a_copy;    /* A parser for handling <D:error> responses from mod_dav_svn.  This   * will be NULL if we haven't processed a COPY request yet.   */  ne_xml_parser *error_parser;  /* If <D:error> is returned, here's where the parsed result goes, or   * NULL otherwise.   */  svn_error_t *err;  /* A place for allocating fields in this structure. */  apr_pool_t *pool;};typedef struct{  svn_ra_dav__session_t *ras;  const char *activity_url;  apr_hash_t *valid_targets;  svn_ra_get_wc_prop_func_t get_func;  svn_ra_push_wc_prop_func_t push_func;  void *cb_baton;  svn_boolean_t disable_merge_response;  /* The (potential) author of this commit. */  const char *user;  /* Log message for the commit. */  const char *log_msg;  /* The commit callback and baton */  svn_commit_callback2_t callback;  void *callback_baton;  /* The hash of lock-tokens owned by the working copy. */  apr_hash_t *tokens;  /* Whether or not to keep the locks after commit is done. */  svn_boolean_t keep_locks;  /* A context for neon COPY request callbacks. */  struct copy_baton *cb;} commit_ctx_t;typedef struct{  apr_file_t *tmpfile;  svn_stringbuf_t *fname;  const char *base_checksum;    /* hex md5 of base text; may be null */} put_baton_t;typedef struct{  commit_ctx_t *cc;  version_rsrc_t *rsrc;  apr_hash_t *prop_changes; /* name/values pairs of new/changed properties. */  apr_array_header_t *prop_deletes; /* names of properties to delete. */  svn_boolean_t created; /* set if this is an add rather than an update */  apr_pool_t *pool; /* the pool from open_foo() / add_foo() */  put_baton_t *put_baton;  /* baton for this file's PUT request */  const char *token;       /* file's lock token, if available */} resource_baton_t;/* this property will be fetched from the server when we don't find it   cached in the WC property store. */static const ne_propname fetch_props[] ={  { "DAV:", "checked-in" },  { NULL }};static const ne_propname log_message_prop = { SVN_DAV_PROP_NS_SVN, "log" };/* perform a deep copy of BASE into POOL, and return the result. */static version_rsrc_t * dup_resource(version_rsrc_t *base, apr_pool_t *pool){  version_rsrc_t *rsrc = apr_pcalloc(pool, sizeof(*rsrc));  rsrc->pool = pool;  rsrc->revision = base->revision;  rsrc->url = base->url ?    apr_pstrdup(pool, base->url) : NULL;  rsrc->vsn_url = base->vsn_url ?    apr_pstrdup(pool, base->vsn_url) : NULL;  rsrc->wr_url = base->wr_url ?    apr_pstrdup(pool, base->wr_url) : NULL;  rsrc->local_path = base->local_path ?     apr_pstrdup(pool, base->local_path) : NULL;  return rsrc;}static svn_error_t * simple_request(svn_ra_dav__session_t *ras,                                     const char *method,                                    const char *url,                                     int *code,                                    apr_hash_t *extra_headers,                                    int okay_1,                                     int okay_2,                                     apr_pool_t *pool){  ne_request *req;  /* create/prep the request */  req = ne_request_create(ras->sess, method, url);  if (req == NULL)    {      return svn_error_createf(SVN_ERR_RA_DAV_CREATING_REQUEST, NULL,                               _("Could not create a request (%s '%s')"),                               method, url);    }  /* add any extra headers passed in by caller. */  if (extra_headers != NULL)    {      apr_hash_index_t *hi;      for (hi = apr_hash_first(pool, extra_headers);           hi; hi = apr_hash_next(hi))        {          const void *key;          void *val;          apr_hash_this(hi, &key, NULL, &val);          ne_add_request_header(req, (const char *) key, (const char *) val);         }    }  /* run the request and get the resulting status code (and svn_error_t) */  return svn_ra_dav__request_dispatch(code, req, ras->sess,                                      method, url, okay_1, okay_2,#ifdef SVN_NEON_0_25                                      NULL, NULL,#endif /* SVN_NEON_0_25 */                                      pool);}static svn_error_t * delete_activity(void *edit_baton,                                     apr_pool_t *pool){  commit_ctx_t *cc = edit_baton;  return simple_request(cc->ras, "DELETE", cc->activity_url, NULL,                        NULL, 204 /* No Content */, 404 /* Not Found */, pool);}/* Get the version resource URL for RSRC, storing it in   RSRC->vsn_url.  Use POOL for all temporary allocations. */static svn_error_t * get_version_url(commit_ctx_t *cc,                                     version_rsrc_t *rsrc,                                     svn_boolean_t force,                                     apr_pool_t *pool){  svn_ra_dav_resource_t *propres;  const char *url;  const svn_string_t *url_str;  if (!force && cc->get_func != NULL)    {      const svn_string_t *vsn_url_value;      SVN_ERR((*cc->get_func)(cc->cb_baton,                              rsrc->local_path,                              SVN_RA_DAV__LP_VSN_URL,                              &vsn_url_value,                              pool));      if (vsn_url_value != NULL)        {          rsrc->vsn_url = apr_pstrdup(rsrc->pool, vsn_url_value->data);          return SVN_NO_ERROR;        }      /* whoops. it wasn't there. go grab it from the server. */    }  if (rsrc->revision == SVN_INVALID_REVNUM)    {      /* We aren't trying to get a specific version -- use the HEAD. We         fetch the version URL from the public URL. */      url = rsrc->url;    }  else    {      svn_string_t bc_url;      svn_string_t bc_relative;      /* The version URL comes from a resource in the Baseline Collection. */      SVN_ERR(svn_ra_dav__get_baseline_info(NULL,                                            &bc_url, &bc_relative, NULL,                                            cc->ras->sess,                                            rsrc->url,                                            rsrc->revision,                                            pool));      url = svn_path_url_add_component(bc_url.data, bc_relative.data, pool);    }  /* Get the DAV:checked-in property, which contains the URL of the     Version Resource */  SVN_ERR(svn_ra_dav__get_props_resource(&propres, cc->ras->sess, url,                                         NULL, fetch_props, pool));  url_str = apr_hash_get(propres->propset,                         SVN_RA_DAV__PROP_CHECKED_IN,                         APR_HASH_KEY_STRING);  if (url_str == NULL)    {      /* ### need a proper SVN_ERR here */      return svn_error_create(APR_EGENERAL, NULL,                              _("Could not fetch the Version Resource URL "                                "(needed during an import or when it is "                                "missing from the local, cached props)"));    }  /* ensure we get the proper lifetime for this URL since it is going into     a resource object. */  rsrc->vsn_url = apr_pstrdup(rsrc->pool, url_str->data);  if (cc->push_func != NULL)    {      /* Now we can store the new version-url. */      SVN_ERR((*cc->push_func)(cc->cb_baton,                               rsrc->local_path,                               SVN_RA_DAV__LP_VSN_URL,                               url_str,                               pool));    }  return SVN_NO_ERROR;}/* When FORCE is true, then we force a query to the server, ignoring any   cached property. */static svn_error_t * get_activity_collection(commit_ctx_t *cc,                                             const svn_string_t **collection,                                             svn_boolean_t force,                                             apr_pool_t *pool){  if (!force && cc->get_func != NULL)    {      /* with a get_func, we can just ask for the activity URL from the         property store. */      /* get the URL where we should create activities */      SVN_ERR((*cc->get_func)(cc->cb_baton,                              "",                              SVN_RA_DAV__LP_ACTIVITY_COLL,                              collection,                              pool));      if (*collection != NULL)        {          /* the property was there. return it. */          return SVN_NO_ERROR;        }      /* property not found for some reason. get it from the server. */    }  /* use our utility function to fetch the activity URL */  SVN_ERR(svn_ra_dav__get_activity_collection(collection,                                              cc->ras,                                              cc->ras->root.path,                                              pool));  if (cc->push_func != NULL)    {      /* save the (new) activity collection URL into the directory */      SVN_ERR((*cc->push_func)(cc->cb_baton,                               "",                               SVN_RA_DAV__LP_ACTIVITY_COLL,                               *collection,                               pool));    }  return SVN_NO_ERROR;}static svn_error_t * create_activity(commit_ctx_t *cc,                                     apr_pool_t *pool){  const svn_string_t * activity_collection;  const char *uuid_buf = svn_uuid_generate(pool);  int code;  const char *url;  /* get the URL where we'll create activities, construct the URL for     the activity, and create the activity.  The URL for our activity     will be ACTIVITY_COLL/UUID */  SVN_ERR(get_activity_collection(cc, &activity_collection, FALSE, pool));  url = svn_path_url_add_component(activity_collection->data,                                    uuid_buf, pool);  SVN_ERR(simple_request(cc->ras, "MKACTIVITY", url, &code, NULL,                         201 /* Created */, 404 /* Not Found */, pool));  /* if we get a 404, then it generally means that the cached activity     collection no longer exists. Retry the sequence, but force a query     to the server for the activity collection. */  if (code == 404)    {      SVN_ERR(get_activity_collection(cc, &activity_collection, TRUE, pool));      url = svn_path_url_add_component(activity_collection->data,                                        uuid_buf, pool);      SVN_ERR(simple_request(cc->ras, "MKACTIVITY", url, &code,                             NULL, 201, 0, pool));    }  cc->activity_url = url;  return SVN_NO_ERROR;}/* Add a child resource.  POOL should be as "temporary" as possible,   but probably not as far as requiring a new temp pool. */static svn_error_t * add_child(version_rsrc_t **child,                               commit_ctx_t *cc,                               const version_rsrc_t *parent,                               const char *name,                               int created,                               svn_revnum_t revision,                               apr_pool_t *pool){  version_rsrc_t *rsrc;  /* ### todo:  This from Yoshiki Hayashi <yoshiki@xemacs.org>:     Probably created flag in add_child can be removed because

⌨️ 快捷键说明

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