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

📄 merge.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * merge.c :  routines for performing a MERGE server requests * * ==================================================================== * Copyright (c) 2000-2005 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>#define APR_WANT_STRFUNC#include <apr_want.h>#include <ne_socket.h>#include <ne_request.h>#include "svn_string.h"#include "svn_error.h"#include "svn_path.h"#include "svn_ra.h"#include "svn_pools.h"#include "svn_props.h"#include "svn_xml.h"#include "svn_private_config.h"#include "ra_dav.h"static const svn_ra_dav__xml_elm_t merge_elements[] ={  { "DAV:", "updated-set", ELEM_updated_set, 0 },  { "DAV:", "merged-set", ELEM_merged_set, 0 },  { "DAV:", "ignored-set", ELEM_ignored_set, 0 },  { "DAV:", "href", ELEM_href, SVN_RA_DAV__XML_CDATA },  { "DAV:", "merge-response", ELEM_merge_response, 0 },  { "DAV:", "checked-in", ELEM_checked_in, 0 },  { "DAV:", "response", ELEM_response, 0 },  { "DAV:", "propstat", ELEM_propstat, 0 },  { "DAV:", "status", ELEM_status, SVN_RA_DAV__XML_CDATA },  { "DAV:", "responsedescription", ELEM_responsedescription,    SVN_RA_DAV__XML_CDATA },  { "DAV:", "prop", ELEM_prop, 0 },  { "DAV:", "resourcetype", ELEM_resourcetype, 0 },  { "DAV:", "collection", ELEM_collection, 0 },  { "DAV:", "baseline", ELEM_baseline, 0 },  { "DAV:", "version-name", ELEM_version_name, SVN_RA_DAV__XML_CDATA },  { SVN_XML_NAMESPACE, "post-commit-err",    ELEM_post_commit_err, SVN_RA_DAV__XML_CDATA },  { "DAV:", "creationdate", ELEM_creationdate, SVN_RA_DAV__XML_CDATA },  { "DAV:", "creator-displayname", ELEM_creator_displayname,    SVN_RA_DAV__XML_CDATA },  { NULL }};enum merge_rtype {  RTYPE_UNKNOWN,    /* unknown (haven't seen it in the response yet) */  RTYPE_REGULAR,    /* a regular (member) resource */  RTYPE_COLLECTION, /* a collection resource */  RTYPE_BASELINE    /* a baseline resource */};typedef struct {  apr_pool_t *pool;  /* a clearable subpool of pool, for loops.  Do not use for anything     that must persist beyond the scope of your function! */  apr_pool_t *scratchpool;  /* any error that may have occurred during the MERGE response handling */  svn_error_t *err;  /* the BASE_HREF contains the merge target. as resources are specified in     the merge response, we make their URLs relative to this URL, thus giving     us a path for use in the commit callbacks. */  const char *base_href;  apr_size_t base_len;  svn_revnum_t rev;        /* the new/target revision number for this commit */  svn_boolean_t response_has_error;  int response_parent;     /* what element did DAV:response appear within? */  int href_parent;         /* what element is the DAV:href appearing within? */  svn_stringbuf_t *href;   /* current response */  int status;              /* HTTP status for this DAV:propstat */  enum merge_rtype rtype;  /* DAV:resourcetype of this resource */  svn_stringbuf_t *vsn_name;       /* DAV:version-name for this resource */  svn_stringbuf_t *vsn_url;        /* DAV:checked-in for this resource */  svn_stringbuf_t *committed_date; /* DAV:creationdate for this resource */  svn_stringbuf_t *last_author;    /* DAV:creator-displayname for this                                      resource */  svn_stringbuf_t *post_commit_err;/* SVN_XML_NAMESPACE:post-commit hook's                                      stderr */  /* We only invoke set_prop() on targets listed in valid_targets.     Some entities (such as directories that have had changes     committed underneath but are not themselves targets) will be     mentioned in the merge response but not appear in     valid_targets. */  apr_hash_t *valid_targets;  /* Client callbacks */  svn_ra_push_wc_prop_func_t push_prop;  void *cb_baton;  /* baton for above */} merge_ctx_t;static void add_ignored(merge_ctx_t *mc, const char *cdata){  /* ### the server didn't check in the file(!) */  /* ### remember the file and issue a report/warning later */}static svn_boolean_t okay_to_bump_path(const char *path,                                       apr_hash_t *valid_targets,                                       apr_pool_t *pool){  svn_stringbuf_t *parent_path;  enum svn_recurse_kind r;  /* Easy check:  if path itself is in the hash, then it's legit. */  if (apr_hash_get(valid_targets, path, APR_HASH_KEY_STRING))    return TRUE;  /* Otherwise, this path is bumpable IFF one of its parents is in the     hash and marked with a 'recursion' flag. */  parent_path = svn_stringbuf_create(path, pool);    do {    apr_size_t len = parent_path->len;    svn_path_remove_component(parent_path);    if (len == parent_path->len)      break;    r = (enum svn_recurse_kind) apr_hash_get(valid_targets,                                             parent_path->data,                                             APR_HASH_KEY_STRING);    if (r == svn_recursive)      return TRUE;  } while (! svn_path_is_empty(parent_path->data));  /* Default answer: if we get here, don't allow the bumping. */  return FALSE;}/* If committed PATH appears in MC->valid_targets, and an MC->push_prop * function exists, then store VSN_URL as the SVN_RA_DAV__LP_VSN_URL * property on PATH.  Use POOL for all allocations.  * * Otherwise, just return SVN_NO_ERROR. */static svn_error_t *bump_resource(merge_ctx_t *mc,                                  const char *path,                                  char *vsn_url,                                  apr_pool_t *pool){  /* no sense in doing any more work if there's no property setting     function at our disposal. */  if (mc->push_prop == NULL)    return SVN_NO_ERROR;  /* Only invoke a client callback on PATH if PATH counts as a     committed target.  The commit-tracking editor built this list for     us, and took care not to include directories unless they were     directly committed (i.e., received a property change). */  if (! okay_to_bump_path(path, mc->valid_targets, pool))    return SVN_NO_ERROR;  /* Okay, NOW set the new version url. */  {    svn_string_t vsn_url_str;  /* prop setter wants an svn_string_t */    vsn_url_str.data = vsn_url;    vsn_url_str.len = strlen(vsn_url);    SVN_ERR((*mc->push_prop)(mc->cb_baton, path,                             SVN_RA_DAV__LP_VSN_URL, &vsn_url_str,                             pool));  }  return SVN_NO_ERROR;}static svn_error_t * handle_resource(merge_ctx_t *mc,                                     apr_pool_t *pool){  const char *relative;  if (mc->response_has_error)    {      /* ### what to do? */      /* ### return "no error", presuming whatever set response_has_error         ### has already handled the problem. */      return SVN_NO_ERROR;    }  if (mc->response_parent == ELEM_merged_set)    {      /* ### shouldn't have happened. we told the server "don't merge" */      /* ### need something better than APR_EGENERAL */      return svn_error_createf(APR_EGENERAL, NULL,                               _("Protocol error: we told the server not to "                                 "auto-merge any resources, but it said that "                                 "'%s' was merged"), mc->href->data);    }  if (mc->response_parent != ELEM_updated_set)    {      /* ### unknown parent for this response(!) */      /* ### need something better than APR_EGENERAL */      return svn_error_createf(APR_EGENERAL, NULL,                               _("Internal error: there is an unknown parent "                                 "(%d) for the 'DAV:response' element within"                                 " the MERGE response"), mc->response_parent);    }#if 0  /* ### right now, the server isn't sending everything for all resources.     ### just skip this requirement. */  if (mc->href->len == 0      || mc->vsn_name->len == 0      || mc->vsn_url->len == 0      || mc->rtype == RTYPE_UNKNOWN)    {      /* one or more properties were missing in the DAV:response for the         resource. */      return svn_error_createf(APR_EGENERAL, NULL,                               _("Protocol error: the MERGE response for the "                                 "'%s' resource did not return all of the "                                 "properties that we asked for (and need to "                                 "complete the commit)"), mc->href->data);    }#endif  if (mc->rtype == RTYPE_BASELINE)    {      /* cool. the DAV:version-name tells us the new revision */      mc->rev = SVN_STR_TO_REV(mc->vsn_name->data);      return SVN_NO_ERROR;    }  /* a collection or regular resource */  if (mc->href->len < mc->base_len)    {      /* ### need something better than APR_EGENERAL */      return svn_error_createf(APR_EGENERAL, NULL,                               _("A MERGE response for '%s' is not a child "                                 "of the destination ('%s')"),                               mc->href->data, mc->base_href);    }  /* given HREF of the form: BASE "/" RELATIVE, extract the relative portion */  if (mc->base_len == mc->href->len)    relative = "";  else    relative = mc->href->data + mc->base_len + 1;  /* bump the resource */  relative = svn_path_uri_decode(relative, pool);  return bump_resource(mc, relative, mc->vsn_url->data, pool);}static int validate_element(void *userdata, svn_ra_dav__xml_elmid parent,                            svn_ra_dav__xml_elmid child){  if ((child == ELEM_collection || child == ELEM_baseline)      && parent != ELEM_resourcetype) {    /* ### technically, they could occur elsewhere, but screw it */    return SVN_RA_DAV__XML_INVALID;  }  switch (parent)    {    case ELEM_root:      if (child == ELEM_merge_response)        return SVN_RA_DAV__XML_VALID;      else        return SVN_RA_DAV__XML_INVALID;    case ELEM_merge_response:      if (child == ELEM_updated_set          || child == ELEM_merged_set          || child == ELEM_ignored_set)        return SVN_RA_DAV__XML_VALID;      else        return SVN_RA_DAV__XML_DECLINE; /* any child is allowed */    case ELEM_updated_set:    case ELEM_merged_set:      if (child == ELEM_response)        return SVN_RA_DAV__XML_VALID;      else        return SVN_RA_DAV__XML_DECLINE; /* ignore if something else                                           was in there */    case ELEM_ignored_set:      if (child == ELEM_href)        return SVN_RA_DAV__XML_VALID;      else        return SVN_RA_DAV__XML_DECLINE; /* ignore if something else                                           was in there */    case ELEM_response:      if (child == ELEM_href          || child == ELEM_status          || child == ELEM_propstat)        return SVN_RA_DAV__XML_VALID;      else if (child == ELEM_responsedescription)        /* ### I think we want this... to save a message for the user */        return SVN_RA_DAV__XML_DECLINE; /* valid, but we don't need to see it */      else        return SVN_RA_DAV__XML_DECLINE; /* ignore if something else                                           was in there */    case ELEM_propstat:      if (child == ELEM_prop || child == ELEM_status)        return SVN_RA_DAV__XML_VALID;      else if (child == ELEM_responsedescription)        /* ### I think we want this... to save a message for the user */        return SVN_RA_DAV__XML_DECLINE; /* valid, but we don't need to see it */      else        return SVN_RA_DAV__XML_DECLINE; /* ignore if something else                                           was in there */    case ELEM_prop:      if (child == ELEM_checked_in          || child == ELEM_resourcetype          || child == ELEM_version_name          || child == ELEM_creationdate          || child == ELEM_creator_displayname          || child == ELEM_post_commit_err          /* other props */)        return SVN_RA_DAV__XML_VALID;      else        return SVN_RA_DAV__XML_DECLINE; /* ignore other props */    case ELEM_checked_in:      if (child == ELEM_href)        return SVN_RA_DAV__XML_VALID;      else        return SVN_RA_DAV__XML_DECLINE; /* ignore if something else                                           was in there */    case ELEM_resourcetype:      if (child == ELEM_collection || child == ELEM_baseline)        return SVN_RA_DAV__XML_VALID;      else        return SVN_RA_DAV__XML_DECLINE; /* ignore if something else                                           was in there */    default:      return SVN_RA_DAV__XML_DECLINE;    }  /* NOTREACHED */}static int start_element(void *userdata, const svn_ra_dav__xml_elm_t *elm,                         const char **atts){  merge_ctx_t *mc = userdata;  switch (elm->id)    {    case ELEM_response:      mc->response_has_error = FALSE;      /* for each response (which corresponds to one resource), note that we         haven't seen its resource type yet */      mc->rtype = RTYPE_UNKNOWN;

⌨️ 快捷键说明

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