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

📄 reporter.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * reporter.c : `reporter' vtable routines for updates. * * ==================================================================== * 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 "svn_path.h"#include "svn_fs.h"#include "svn_repos.h"#include "svn_pools.h"#include "svn_md5.h"#include "svn_props.h"#include "repos.h"#include "svn_private_config.h"#define NUM_CACHED_SOURCE_ROOTS 4/* Theory of operation: we write report operations out to a temporary   file as we receive them.  When the report is finished, we read the   operations back out again, using them to guide the progression of   the delta between the source and target revs.   Temporary file format: we use a simple ad-hoc format to store the   report operations.  Each report operation is the concatention of   the following ("+/-" indicates the single character '+' or '-';   <length> and <revnum> are written out as decimal strings):     +/-                      '-' marks the end of the report     If previous is +:       <length>:<bytes>       Length-counted path string       +/-                    '+' indicates the presence of link_path       If previous is +:         <length>:<bytes>     Length-counted link_path string       +/-                    '+' indicates presence of revnum       If previous is +:         <revnum>:            Revnum of set_path or link_path       +/-                    '+' indicates start_empty field set       +/-                    '+' indicates presence of lock_token field.       If previous is +:         <length>:<bytes>     Length-counted lock_token string   Terminology: for brevity, this file frequently uses the prefixes   "s_" for source, "t_" for target, and "e_" for editor.  Also, to   avoid overloading the word "target", we talk about the source   "anchor and operand", rather than the usual "anchor and target". *//* Describes the state of a working copy subtree, as given by a   report.  Because we keep a lookahead pathinfo, we need to allocate   each one of these things in a subpool of the report baton and free   it when done. */typedef struct path_info_t{  const char *path;            /* path, munged to be anchor-relative */  const char *link_path;       /* NULL for set_path or delete_path */  svn_revnum_t rev;            /* SVN_INVALID_REVNUM for delete_path */  svn_boolean_t start_empty;   /* Meaningless for delete_path */  const char *lock_token;      /* NULL if no token */  apr_pool_t *pool;            /* Container pool */} path_info_t;/* A structure used by the routines within the `reporter' vtable,   driven by the client as it describes its working copy revisions. */typedef struct report_baton_t{  /* Parameters remembered from svn_repos_begin_report */  svn_repos_t *repos;  const char *fs_base;         /* FS path corresponding to wc anchor */  const char *s_operand;       /* Anchor-relative wc target (may be empty) */  svn_revnum_t t_rev;          /* Revnum which the edit will bring the wc to */  const char *t_path;          /* FS path the edit will bring the wc to */  svn_boolean_t text_deltas;   /* Whether to report text deltas */  svn_boolean_t recurse;  svn_boolean_t ignore_ancestry;  svn_boolean_t is_switch;  const svn_delta_editor_t *editor;  void *edit_baton;   svn_repos_authz_func_t authz_read_func;  void *authz_read_baton;  /* The temporary file in which we are stashing the report. */  apr_file_t *tempfile;  /* For the actual editor drive, we'll need a lookahead path info     entry, a cache of FS roots, and a pool to store them. */  path_info_t *lookahead;  svn_fs_root_t *t_root;  svn_fs_root_t *s_roots[NUM_CACHED_SOURCE_ROOTS];  apr_pool_t *pool;} report_baton_t;/* The type of a function that accepts changes to an object's property   list.  OBJECT is the object whose properties are being changed.   NAME is the name of the property to change.  VALUE is the new value   for the property, or zero if the property should be deleted. */typedef svn_error_t *proplist_change_fn_t(report_baton_t *b, void *object,                                          const char *name,                                          const svn_string_t *value,                                          apr_pool_t *pool);static svn_error_t *delta_dirs(report_baton_t *b, svn_revnum_t s_rev,                               const char *s_path, const char *t_path,                               void *dir_baton, const char *e_path,                               svn_boolean_t start_empty, apr_pool_t *pool);/* --- READING PREVIOUSLY STORED REPORT INFORMATION --- */static svn_error_t *read_number(apr_uint64_t *num, apr_file_t *temp, apr_pool_t *pool){  char c;  *num = 0;  while (1)    {      SVN_ERR(svn_io_file_getc(&c, temp, pool));      if (c == ':')        break;      *num = *num * 10 + (c - '0');    }  return SVN_NO_ERROR;}static svn_error_t *read_string(const char **str, apr_file_t *temp, apr_pool_t *pool){  apr_uint64_t len;  char *buf;  SVN_ERR(read_number(&len, temp, pool));  buf = apr_palloc(pool, len + 1);  SVN_ERR(svn_io_file_read_full(temp, buf, len, NULL, pool));  buf[len] = 0;  *str = buf;  return SVN_NO_ERROR;}static svn_error_t *read_rev(svn_revnum_t *rev, apr_file_t *temp, apr_pool_t *pool){  char c;  apr_uint64_t num;  SVN_ERR(svn_io_file_getc(&c, temp, pool));  if (c == '+')    {      SVN_ERR(read_number(&num, temp, pool));      *rev = num;    }  else    *rev = SVN_INVALID_REVNUM;  return SVN_NO_ERROR;}/* Read a report operation *PI out of TEMP.  Set *PI to NULL if we   have reached the end of the report. */static svn_error_t *read_path_info(path_info_t **pi, apr_file_t *temp, apr_pool_t *pool){  char c;  SVN_ERR(svn_io_file_getc(&c, temp, pool));  if (c == '-')    {      *pi = NULL;      return SVN_NO_ERROR;    }  *pi = apr_palloc(pool, sizeof(**pi));  SVN_ERR(read_string(&(*pi)->path, temp, pool));  SVN_ERR(svn_io_file_getc(&c, temp, pool));  if (c == '+')    SVN_ERR(read_string(&(*pi)->link_path, temp, pool));  else    (*pi)->link_path = NULL;  SVN_ERR(read_rev(&(*pi)->rev, temp, pool));  SVN_ERR(svn_io_file_getc(&c, temp, pool));  (*pi)->start_empty = (c == '+');  SVN_ERR(svn_io_file_getc(&c, temp, pool));  if (c == '+')    SVN_ERR(read_string(&(*pi)->lock_token, temp, pool));  else    (*pi)->lock_token = NULL;  (*pi)->pool = pool;  return SVN_NO_ERROR;}/* Return true if PI's path is a child of PREFIX (which has length PLEN). */static svn_boolean_t relevant(path_info_t *pi, const char *prefix, apr_size_t plen){  return (pi && strncmp(pi->path, prefix, plen) == 0 &&          (!*prefix || pi->path[plen] == '/'));}/* Fetch the next pathinfo from B->tempfile for a descendent of   PREFIX.  If the next pathinfo is for an immediate child of PREFIX,   set *ENTRY to the path component of the report information and   *INFO to the path information for that entry.  If the next pathinfo   is for a grandchild or other more remote descendent of PREFIX, set   *ENTRY to the immediate child corresponding to that descendent and   set *INFO to NULL.  If the next pathinfo is not for a descendent of   PREFIX, or if we reach the end of the report, set both *ENTRY and   *INFO to NULL.   At all times, B->lookahead is presumed to be the next pathinfo not   yet returned as an immediate child, or NULL if we have reached the   end of the report.  Because we use a lookahead element, we can't   rely on the usual nested pool lifetimes, so allocate each pathinfo   in a subpool of the report baton's pool.  The caller should delete   (*INFO)->pool when it is done with the information. */static svn_error_t *fetch_path_info(report_baton_t *b, const char **entry, path_info_t **info,                const char *prefix, apr_pool_t *pool){  apr_size_t plen = strlen(prefix);  const char *relpath, *sep;  apr_pool_t *subpool;  if (!relevant(b->lookahead, prefix, plen))    {      /* No more entries relevant to prefix. */      *entry = NULL;      *info = NULL;    }  else    {      /* Take a look at the prefix-relative part of the path. */      relpath = b->lookahead->path + (*prefix ? plen + 1 : 0);      sep = strchr(relpath, '/');      if (sep)        {          /* Return the immediate child part; do not advance. */          *entry = apr_pstrmemdup(pool, relpath, sep - relpath);          *info = NULL;        }      else        {          /* This is an immediate child; return it and advance. */          *entry = relpath;          *info = b->lookahead;          subpool = svn_pool_create(b->pool);          SVN_ERR(read_path_info(&b->lookahead, b->tempfile, subpool));        }    }  return SVN_NO_ERROR;}/* Skip all path info entries relevant to *PREFIX.  Call this when the   editor drive skips a directory. */static svn_error_t *skip_path_info(report_baton_t *b, const char *prefix){  apr_size_t plen = strlen(prefix);  apr_pool_t *subpool;  while (relevant(b->lookahead, prefix, plen))    {      svn_pool_destroy(b->lookahead->pool);      subpool = svn_pool_create(b->pool);      SVN_ERR(read_path_info(&b->lookahead, b->tempfile, subpool));    }  return SVN_NO_ERROR;}/* Return true if there is at least one path info entry relevant to *PREFIX. */static svn_boolean_tany_path_info(report_baton_t *b, const char *prefix){  return relevant(b->lookahead, prefix, strlen(prefix));}/* --- DRIVING THE EDITOR ONCE THE REPORT IS FINISHED --- *//* While driving the editor, the target root will remain constant, but   we may have to jump around between source roots depending on the   state of the working copy.  If we were to open a root each time we   revisit a rev, we would get no benefit from node-id caching; on the   other hand, if we hold open all the roots we ever visit, we'll use   an unbounded amount of memory.  As a compromise, we maintain a   fixed-size LRU cache of source roots.  get_source_root retrieves a   root from the cache, using POOL to allocate the new root if   necessary.  Be careful not to hold onto the root for too long,   particularly after recursing, since another call to get_source_root   can close it. */static svn_error_t *get_source_root(report_baton_t *b, svn_fs_root_t **s_root, svn_revnum_t rev){  int i;  svn_fs_root_t *root, *prev = NULL;  /* Look for the desired root in the cache, sliding all the unmatched     entries backwards a slot to make room for the right one. */  for (i = 0; i < NUM_CACHED_SOURCE_ROOTS; i++)    {      root = b->s_roots[i];      b->s_roots[i] = prev;      if (root && svn_fs_revision_root_revision(root) == rev)        break;      prev = root;    }  /* If we didn't find it, throw out the oldest root and open a new one. */  if (i == NUM_CACHED_SOURCE_ROOTS)    {      if (prev)        svn_fs_close_root(prev);      SVN_ERR(svn_fs_revision_root(&root, b->repos->fs, rev, b->pool));    }  /* Assign the desired root to the first cache slot and hand it back. */  b->s_roots[0] = root;  *s_root = root;  return SVN_NO_ERROR;}/* Call the directory property-setting function of B->editor to set   the property NAME to VALUE on DIR_BATON. */static svn_error_t *change_dir_prop(report_baton_t *b, void *dir_baton, const char *name,                 const svn_string_t *value, apr_pool_t *pool){  return b->editor->change_dir_prop(dir_baton, name, value, pool);}/* Call the file property-setting function of B->editor to set the   property NAME to VALUE on FILE_BATON. */static svn_error_t *change_file_prop(report_baton_t *b, void *file_baton, const char *name,                  const svn_string_t *value, apr_pool_t *pool){  return b->editor->change_file_prop(file_baton, name, value, pool);}/* Generate the appropriate property editing calls to turn the   properties of S_REV/S_PATH into those of B->t_root/T_PATH.  If   S_PATH is NULL, this is an add, so assume the target starts with no   properties.  Pass OBJECT on to the editor function wrapper   CHANGE_FN. */static svn_error_t *delta_proplists(report_baton_t *b, svn_revnum_t s_rev, const char *s_path,                const char *t_path, const char *lock_token,

⌨️ 快捷键说明

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