📄 update.c
字号:
/* * update.c : entry point for update RA 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/. * ==================================================================== */#define APR_WANT_STRFUNC#include <apr_want.h>#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_base64.h"#include "svn_private_config.h"#include "ra_serf.h"/* * This enum represents the current state of our XML parsing for a REPORT. * * A little explanation of how the parsing works. Every time we see * an open-directory tag, we enter the OPEN_DIR state. Likewise, for * add-directory, open-file, etc. When we see the closing variant of the * open-directory tag, we'll 'pop' out of that state. * * Each state has a pool associated with it that can have temporary * allocations that will live as long as the tag is opened. Once * the tag is 'closed', the pool will be reused. */typedef enum { NONE = 0, OPEN_DIR, ADD_DIR, OPEN_FILE, ADD_FILE, PROP, IGNORE_PROP_NAME, NEED_PROP_NAME,} report_state_e;/* * This structure represents the information for a directory. */typedef struct report_dir_t{ /* Our parent directory. * * This value is NULL when we are the root. */ struct report_dir_t *parent_dir; apr_pool_t *pool; /* Our name sans any parents. */ const char *base_name; /* the expanded directory name (including all parent names) */ const char *name; /* temporary path buffer for this directory. */ svn_stringbuf_t *name_buf; /* the canonical url for this directory. */ const char *url; /* Our base revision - SVN_INVALID_REVNUM if we're adding this dir. */ svn_revnum_t base_rev; /* The target revision we're retrieving. */ svn_revnum_t target_rev; /* controlling dir baton - this is only created in open_dir() */ void *dir_baton; apr_pool_t *dir_baton_pool; /* Our master update editor and baton. */ const svn_delta_editor_t *update_editor; void *update_baton; /* How many references to this directory do we still have open? */ apr_size_t ref_count; /* Namespace list allocated out of this ->pool. */ svn_ra_serf__ns_t *ns_list; /* hashtable for all of the properties (shared within a dir) */ apr_hash_t *props; /* hashtable for all to-be-removed properties (shared within a dir) */ apr_hash_t *removed_props; /* The propfind request for our current directory */ svn_ra_serf__propfind_context_t *propfind; /* Has the server told us to fetch the dir props? */ svn_boolean_t fetch_props; /* Have we closed the directory tag (meaning no more additions)? */ svn_boolean_t tag_closed; /* The children of this directory */ struct report_dir_t *children; /* The next sibling of this directory */ struct report_dir_t *sibling;} report_dir_t;/* * This structure represents the information for a file. * * A directory may have a report_info_t associated with it as well. * * This structure is created as we parse the REPORT response and * once the element is completed, we create a report_fetch_t structure * to give to serf to retrieve this file. */typedef struct report_info_t{ apr_pool_t *pool; /* The enclosing directory. * * If this structure refers to a directory, the dir it points to will be * itself. */ report_dir_t *dir; /* Our name sans any directory info. */ const char *base_name; /* the expanded file name (including all parent directory names) */ const char *name; /* file name buffer */ svn_stringbuf_t *name_buf; /* the canonical url for this file. */ const char *url; /* lock token, if we had one to start off with. */ const char *lock_token; /* Our base revision - SVN_INVALID_REVNUM if we're adding this file. */ svn_revnum_t base_rev; /* The target revision we're retrieving. */ svn_revnum_t target_rev; /* our delta base, if present (NULL if we're adding the file) */ const svn_string_t *delta_base; /* The propfind request for our current file (if present) */ svn_ra_serf__propfind_context_t *propfind; /* Has the server told us to fetch the file props? */ svn_boolean_t fetch_props; /* Has the server told us to go fetch - only valid if we had it already */ svn_boolean_t fetch_file; /* The properties for this file */ apr_hash_t *props; /* pool passed to update->add_file, etc. */ apr_pool_t *editor_pool; /* controlling file_baton and textdelta handler */ void *file_baton; svn_txdelta_window_handler_t textdelta; void *textdelta_baton; /* temporary property for this file which is currently being parsed * It will eventually be stored in our parent directory's property hash. */ const char *prop_ns; const char *prop_name; const char *prop_val; apr_size_t prop_val_len; const char *prop_encoding;} report_info_t;/* * This structure represents a single request to GET (fetch) a file with * its associated Serf session/connection. */typedef struct report_fetch_t { /* Our pool. */ apr_pool_t *pool; /* Non-NULL if we received an error during processing. */ svn_error_t *err; /* The session we should use to fetch the file. */ svn_ra_serf__session_t *sess; /* The connection we should use to fetch file. */ svn_ra_serf__connection_t *conn; /* Stores the information for the file we want to fetch. */ report_info_t *info; /* Have we read our response headers yet? */ svn_boolean_t read_headers; /* This flag is set when our response is aborted before we reach the * end and we decide to requeue this request. */ svn_boolean_t aborted_read; apr_off_t aborted_read_size; /* This is the amount of data that we have read so far. */ apr_off_t read_size; /* If we're receiving an svndiff, this will be non-NULL. */ svn_stream_t *delta_stream; /* If we're writing this file to a stream, this will be non-NULL. */ svn_stream_t *target_stream; /* Are we done fetching this file? */ svn_boolean_t done; svn_ra_serf__list_t **done_list; svn_ra_serf__list_t done_item;} report_fetch_t;/* * The master structure for a REPORT request and response. */typedef struct { apr_pool_t *pool; svn_ra_serf__session_t *sess; svn_ra_serf__connection_t *conn; /* Source path and destination path */ const char *source; const char *destination; /* Our update target. */ const char *update_target; /* What is the target revision that we want for this REPORT? */ svn_revnum_t target_rev; /* Have we been asked to ignore ancestry, recursion, or textdeltas? */ svn_boolean_t ignore_ancestry; svn_boolean_t recurse; svn_boolean_t text_deltas; apr_hash_t *lock_path_tokens; /* Our master update editor and baton. */ const svn_delta_editor_t *update_editor; void *update_baton; /* The request body for the REPORT. */ serf_bucket_t *buckets; /* root directory object */ report_dir_t *root_dir; /* number of pending GET requests */ unsigned int active_fetches; /* completed fetches (contains report_fetch_t) */ svn_ra_serf__list_t *done_fetches; /* number of pending PROPFIND requests */ unsigned int active_propfinds; /* completed PROPFIND requests (contains propfind_context_t) */ svn_ra_serf__list_t *done_propfinds; /* list of files that will only have prop changes (contains report_info_t) */ svn_ra_serf__list_t *file_propchanges_only; /* The path to the REPORT request */ const char *path; /* Are we done parsing the REPORT response? */ svn_boolean_t done;} report_context_t;/** Report state management helper **/static report_info_t *push_state(svn_ra_serf__xml_parser_t *parser, report_context_t *ctx, report_state_e state){ report_info_t *info; apr_pool_t *info_parent_pool; svn_ra_serf__xml_push_state(parser, state); info = parser->state->private; /* Our private pool needs to be disjoint from the state pool. */ if (!info) { info_parent_pool = ctx->pool; } else { info_parent_pool = info->pool; } if (state == OPEN_DIR || state == ADD_DIR) { report_info_t *new_info; new_info = apr_palloc(info_parent_pool, sizeof(*new_info)); apr_pool_create(&new_info->pool, info_parent_pool); new_info->lock_token = NULL; new_info->dir = apr_pcalloc(new_info->pool, sizeof(*new_info->dir)); new_info->dir->pool = new_info->pool; /* Create the root property tree. */ new_info->dir->props = apr_hash_make(new_info->pool); new_info->props = new_info->dir->props; new_info->dir->removed_props = apr_hash_make(new_info->pool); /* Point to the update_editor */ new_info->dir->update_editor = ctx->update_editor; new_info->dir->update_baton = ctx->update_baton; if (info) { info->dir->ref_count++; new_info->dir->parent_dir = info->dir; /* Point our ns_list at our parents to try to reuse it. */ new_info->dir->ns_list = info->dir->ns_list; /* Add ourselves to our parent's list */ new_info->dir->sibling = info->dir->children; info->dir->children = new_info->dir; } else { /* Allow us to be found later. */ ctx->root_dir = new_info->dir; } parser->state->private = new_info; } else if (state == OPEN_FILE || state == ADD_FILE) { report_info_t *new_info; new_info = apr_palloc(info_parent_pool, sizeof(*new_info)); apr_pool_create(&new_info->pool, info_parent_pool); new_info->file_baton = NULL; new_info->lock_token = NULL; new_info->fetch_file = FALSE; /* Point at our parent's directory state. */ new_info->dir = info->dir; info->dir->ref_count++; new_info->props = apr_hash_make(new_info->pool); parser->state->private = new_info; } return parser->state->private;}/** Wrappers around our various property walkers **/static svn_error_t *set_file_props(void *baton, const char *ns, apr_ssize_t ns_len, const char *name, apr_ssize_t name_len, const svn_string_t *val, apr_pool_t *pool){ report_info_t *info = baton; const svn_delta_editor_t *editor = info->dir->update_editor; return svn_ra_serf__set_baton_props(editor->change_file_prop, info->file_baton, ns, ns_len, name, name_len, val, pool);}static svn_error_t *set_dir_props(void *baton, const char *ns, apr_ssize_t ns_len, const char *name, apr_ssize_t name_len, const svn_string_t *val, apr_pool_t *pool){ report_dir_t *dir = baton; return svn_ra_serf__set_baton_props(dir->update_editor->change_dir_prop, dir->dir_baton, ns, ns_len, name, name_len, val, pool);}static svn_error_t *remove_file_props(void *baton, const char *ns, apr_ssize_t ns_len, const char *name, apr_ssize_t name_len, const svn_string_t *val, apr_pool_t *pool){ report_info_t *info = baton;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -