📄 replay.c
字号:
/* * replay.c : routines for replaying revisions * * ==================================================================== * Copyright (c) 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 "svn_base64.h"#include "svn_pools.h"#include "svn_xml.h"#include "../libsvn_ra/ra_loader.h"#include "ra_dav.h"typedef struct { /* The underlying editor and baton we're replaying into. */ const svn_delta_editor_t *editor; void *edit_baton; /* Any error that occurs during the replay is stored here, so it can be * returned after we bail out of the XML parsing. */ svn_error_t *err; /* Parent pool for the whole reply. */ apr_pool_t *pool; /* Stack of in progress directories, holds dir_item_t objects. */ apr_array_header_t *dirs; /* Cached file baton so we can pass it between the add/open file and * apply textdelta portions of the editor drive. */ void *file_baton; /* Variables required to decode and apply our svndiff data off the wire. */ svn_txdelta_window_handler_t whandler; void *whandler_baton; svn_stream_t *svndiff_decoder; svn_stream_t *base64_decoder; /* A scratch pool used to allocate property data. */ apr_pool_t *prop_pool; /* The name of a property that's being modified. */ const char *prop_name; /* A stringbuf that holds the contents of a property being changed, if this * is NULL it means that the property is being deleted. */ svn_stringbuf_t *prop_accum;} replay_baton_t;#define TOP_DIR(rb) (((dir_item_t *)(rb)->dirs->elts)[(rb)->dirs->nelts - 1])/* Info about a given directory we've seen. */typedef struct { void *baton; const char *path; apr_pool_t *pool; apr_pool_t *file_pool;} dir_item_t;static voidpush_dir(replay_baton_t *rb, void *baton, const char *path, apr_pool_t *pool){ dir_item_t *di = apr_array_push(rb->dirs); di->baton = baton; di->path = apr_pstrdup(pool, path); di->pool = pool; di->file_pool = svn_pool_create(pool);}static const svn_ra_dav__xml_elm_t editor_report_elements[] ={ { SVN_XML_NAMESPACE, "editor-report", ELEM_editor_report, 0 }, { SVN_XML_NAMESPACE, "target-revision", ELEM_target_revision, 0 }, { SVN_XML_NAMESPACE, "open-root", ELEM_open_root, 0 }, { SVN_XML_NAMESPACE, "delete-entry", ELEM_delete_entry, 0 }, { SVN_XML_NAMESPACE, "open-directory", ELEM_open_directory, 0 }, { SVN_XML_NAMESPACE, "add-directory", ELEM_add_directory, 0 }, { SVN_XML_NAMESPACE, "open-file", ELEM_open_file, 0 }, { SVN_XML_NAMESPACE, "add-file", ELEM_add_file, 0 }, { SVN_XML_NAMESPACE, "close-file", ELEM_close_file, 0 }, { SVN_XML_NAMESPACE, "close-directory", ELEM_close_directory, 0 }, { SVN_XML_NAMESPACE, "apply-textdelta", ELEM_apply_textdelta, 0 }, { SVN_XML_NAMESPACE, "change-file-prop", ELEM_change_file_prop, 0 }, { SVN_XML_NAMESPACE, "change-dir-prop", ELEM_change_dir_prop, 0 }, { NULL }};static intstart_element(void *baton, int parent_state, const char *nspace, const char *elt_name, const char **atts){ replay_baton_t *rb = baton; const svn_ra_dav__xml_elm_t *elm = svn_ra_dav__lookup_xml_elem(editor_report_elements, nspace, elt_name); if (! elm) return NE_XML_DECLINE; if (parent_state == ELEM_root) { /* If we're at the root of the tree, the element has to be the editor * report itself. */ if (elm->id != ELEM_editor_report) return SVN_RA_DAV__XML_INVALID; } else if (parent_state != ELEM_editor_report) { /* If we're not at the root, our parent has to be the editor report, * since we don't actually nest any elements. */ return SVN_RA_DAV__XML_INVALID; } switch (elm->id) { case ELEM_target_revision: { const char *crev = svn_xml_get_attr_value("rev", atts); if (! crev) rb->err = svn_error_create (SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, _("Missing revision attr in target-revision element")); else rb->err = rb->editor->set_target_revision(rb->edit_baton, SVN_STR_TO_REV(crev), rb->pool); } break; case ELEM_open_root: { const char *crev = svn_xml_get_attr_value("rev", atts); if (! crev) rb->err = svn_error_create (SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, _("Missing revision attr in open-root element")); else { apr_pool_t *subpool = svn_pool_create(rb->pool); void *dir_baton; rb->err = rb->editor->open_root(rb->edit_baton, SVN_STR_TO_REV(crev), subpool, &dir_baton); push_dir(rb, dir_baton, "", subpool); } } break; case ELEM_delete_entry: { const char *path = svn_xml_get_attr_value("name", atts); const char *crev = svn_xml_get_attr_value("rev", atts); if (! path) rb->err = svn_error_create (SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, _("Missing name attr in delete-entry element")); else if (! crev) rb->err = svn_error_create (SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, _("Missing rev attr in delete-entry element")); else { dir_item_t *di = &TOP_DIR(rb); rb->err = rb->editor->delete_entry(path, SVN_STR_TO_REV(crev), di->baton, di->pool); } } break; case ELEM_open_directory: case ELEM_add_directory: { const char *crev = svn_xml_get_attr_value("rev", atts); const char *name = svn_xml_get_attr_value("name", atts); if (! name) rb->err = svn_error_create (SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, _("Missing name attr in open-directory element")); else { dir_item_t *parent = &TOP_DIR(rb); apr_pool_t *subpool = svn_pool_create(parent->pool); svn_revnum_t rev; void *dir_baton; if (crev) rev = SVN_STR_TO_REV(crev); else rev = SVN_INVALID_REVNUM; if (elm->id == ELEM_open_directory) rb->err = rb->editor->open_directory(name, parent->baton, rev, subpool, &dir_baton); else if (elm->id == ELEM_add_directory) { const char *cpath = svn_xml_get_attr_value("copyfrom-path", atts); crev = svn_xml_get_attr_value("copyfrom-rev", atts); if (crev) rev = SVN_STR_TO_REV(crev); else rev = SVN_INVALID_REVNUM; rb->err = rb->editor->add_directory(name, parent->baton, cpath, rev, subpool, &dir_baton); } else abort(); push_dir(rb, dir_baton, name, subpool); } } break; case ELEM_open_file: case ELEM_add_file: { const char *path = svn_xml_get_attr_value("name", atts); svn_revnum_t rev; dir_item_t *parent = &TOP_DIR(rb); if (! path) { rb->err = svn_error_createf (SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, _("Missing name attr in %s element"), elm->id == ELEM_open_file ? "open-file" : "add-file"); break; } svn_pool_clear(parent->file_pool); if (elm->id == ELEM_add_file) { const char *cpath = svn_xml_get_attr_value("copyfrom-path", atts); const char *crev = svn_xml_get_attr_value("copyfrom-rev", atts); if (crev) rev = SVN_STR_TO_REV(crev);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -