📄 merge.c
字号:
/* * merge.c : MERGE response parsing functions for ra_serf * * ==================================================================== * Copyright (c) 2006 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_uri.h>#include <expat.h>#include <serf.h>#include "svn_pools.h"#include "svn_ra.h"#include "svn_dav.h"#include "svn_xml.h"#include "../libsvn_ra/ra_loader.h"#include "svn_config.h"#include "svn_delta.h"#include "svn_version.h"#include "svn_path.h"#include "svn_private_config.h"#include "ra_serf.h"/* * This enum represents the current state of our XML parsing for a MERGE. */typedef enum { NONE = 0, MERGE_RESPONSE, UPDATED_SET, RESPONSE, HREF, PROPSTAT, PROP, RESOURCE_TYPE, AUTHOR, NAME, DATE, IGNORE_PROP_NAME, NEED_PROP_NAME, PROP_VAL,} merge_state_e;typedef enum { UNSET, BASELINE, COLLECTION, CHECKED_IN,} resource_type_e;typedef struct { /* Temporary allocations here please */ apr_pool_t *pool; resource_type_e type; apr_hash_t *props; const char *prop_ns; const char *prop_name; const char *prop_val; apr_size_t prop_val_len;} merge_info_t;/* Structure associated with a MERGE request. */struct svn_ra_serf__merge_context_t{ apr_pool_t *pool; svn_ra_serf__session_t *session; apr_hash_t *lock_tokens; svn_boolean_t keep_locks; const char *activity_url; apr_size_t activity_url_len; const char *merge_url; apr_size_t merge_url_len; int status; svn_boolean_t done; svn_commit_info_t *commit_info;};static merge_info_t *push_state(svn_ra_serf__xml_parser_t *parser, svn_ra_serf__merge_context_t *ctx, merge_state_e state){ merge_info_t *info; svn_ra_serf__xml_push_state(parser, state); if (state == RESPONSE) { info = apr_palloc(parser->state->pool, sizeof(*info)); info->pool = parser->state->pool; info->props = apr_hash_make(info->pool); parser->state->private = info; } return parser->state->private;}static svn_error_t *start_merge(svn_ra_serf__xml_parser_t *parser, void *userData, svn_ra_serf__dav_props_t name, const char **attrs){ svn_ra_serf__merge_context_t *ctx = userData; apr_pool_t *pool; merge_state_e state; merge_info_t *info; state = parser->state->current_state; if (state == NONE && strcmp(name.name, "merge-response") == 0) { push_state(parser, ctx, MERGE_RESPONSE); } else if (state == NONE) { /* do nothing as we haven't seen our valid start tag yet. */ } else if (state == MERGE_RESPONSE && strcmp(name.name, "updated-set") == 0) { push_state(parser, ctx, UPDATED_SET); } else if (state == UPDATED_SET && strcmp(name.name, "response") == 0) { push_state(parser, ctx, RESPONSE); } else if (state == RESPONSE && strcmp(name.name, "href") == 0) { info = push_state(parser, ctx, PROP_VAL); info->prop_ns = name.namespace; info->prop_name = apr_pstrdup(info->pool, name.name); info->prop_val = NULL; info->prop_val_len = 0; } else if (state == RESPONSE && strcmp(name.name, "propstat") == 0) { push_state(parser, ctx, PROPSTAT); } else if (state == PROPSTAT && strcmp(name.name, "prop") == 0) { push_state(parser, ctx, PROP); } else if (state == PROPSTAT && strcmp(name.name, "status") == 0) { /* Do nothing for now. */ } else if (state == PROP && strcmp(name.name, "resourcetype") == 0) { info = push_state(parser, ctx, RESOURCE_TYPE); info->type = UNSET; } else if (state == RESOURCE_TYPE && strcmp(name.name, "baseline") == 0) { info = parser->state->private; info->type = BASELINE; } else if (state == RESOURCE_TYPE && strcmp(name.name, "collection") == 0) { info = parser->state->private; info->type = COLLECTION; } else if (state == PROP && strcmp(name.name, "checked-in") == 0) { info = push_state(parser, ctx, IGNORE_PROP_NAME); info->prop_ns = name.namespace; info->prop_name = apr_pstrdup(info->pool, name.name); info->prop_val = NULL; info->prop_val_len = 0; } else if (state == PROP) { push_state(parser, ctx, PROP_VAL); } else if (state == IGNORE_PROP_NAME) { push_state(parser, ctx, PROP_VAL); } else if (state == NEED_PROP_NAME) { info = push_state(parser, ctx, PROP_VAL); info->prop_ns = name.namespace; info->prop_name = apr_pstrdup(info->pool, name.name); info->prop_val = NULL; info->prop_val_len = 0; } else { abort(); } return SVN_NO_ERROR;}static svn_error_t *end_merge(svn_ra_serf__xml_parser_t *parser, void *userData, svn_ra_serf__dav_props_t name){ svn_ra_serf__merge_context_t *ctx = userData; merge_state_e state; merge_info_t *info; state = parser->state->current_state; info = parser->state->private; if (state == NONE) { /* nothing to close yet. */ return SVN_NO_ERROR; } if (state == RESPONSE && strcmp(name.name, "response") == 0) { if (info->type == BASELINE) { const char *str; str = apr_hash_get(info->props, "version-name", APR_HASH_KEY_STRING); if (str) { ctx->commit_info->revision = SVN_STR_TO_REV(str); } else { ctx->commit_info->revision = SVN_INVALID_REVNUM; } ctx->commit_info->date = apr_pstrdup(ctx->pool, apr_hash_get(info->props, "creationdate", APR_HASH_KEY_STRING)); ctx->commit_info->author = apr_pstrdup(ctx->pool, apr_hash_get(info->props, "creator-displayname", APR_HASH_KEY_STRING)); ctx->commit_info->post_commit_err = apr_pstrdup(ctx->pool, apr_hash_get(info->props, "post-commit-err", APR_HASH_KEY_STRING)); } else if (ctx->session->wc_callbacks->push_wc_prop) { const char *href, *checked_in; svn_string_t checked_in_str; apr_size_t href_len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -