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

📄 tree.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
  :                                                                            \    svn_error_createf                                                          \      (SVN_ERR_FS_ALREADY_EXISTS, 0,                                           \       _("File already exists: filesystem '%s', revision %ld, path '%s'"),     \       r->fs->path, r->rev, p)                                                 \  )#define NOT_TXN(r)                                 \  svn_error_create                                 \    (SVN_ERR_FS_NOT_TXN_ROOT, NULL,                \     _("Root object must be a transaction root"))/* Getting dag nodes for roots.  *//* Set *NODE_P to a freshly opened dag node referring to the root   directory of ROOT, as part of TRAIL.  */static svn_error_t *root_node(dag_node_t **node_p,          svn_fs_root_t *root,          trail_t *trail,          apr_pool_t *pool){  base_root_data_t *brd = root->fsap_data;  if (! root->is_txn_root)    {      /* It's a revision root, so we already have its root directory         opened.  */      *node_p = svn_fs_base__dag_dup(brd->root_dir, pool);      return SVN_NO_ERROR;    }  else    {      /* It's a transaction root.  Open a fresh copy.  */      return svn_fs_base__dag_txn_root(node_p, root->fs, root->txn,                                        trail, pool);    }}/* Set *NODE_P to a mutable root directory for ROOT, cloning if   necessary, as part of TRAIL.  ROOT must be a transaction root.  Use   ERROR_PATH in error messages.  */static svn_error_t *mutable_root_node(dag_node_t **node_p,                  svn_fs_root_t *root,                  const char *error_path,                  trail_t *trail,                  apr_pool_t *pool){  if (root->is_txn_root)    return svn_fs_base__dag_clone_root(node_p, root->fs, root->txn,                                        trail, pool);  else    /* If it's not a transaction root, we can't change its contents.  */    return svn_fs_base__err_not_mutable(root->fs, root->rev, error_path);}/* Traversing directory paths.  */typedef enum copy_id_inherit_t{  copy_id_inherit_unknown = 0,  copy_id_inherit_self,  copy_id_inherit_parent,  copy_id_inherit_new} copy_id_inherit_t;/* A linked list representing the path from a node up to a root   directory.  We use this for cloning, and for operations that need   to deal with both a node and its parent directory.  For example, a   `delete' operation needs to know that the node actually exists, but   also needs to change the parent directory.  */typedef struct parent_path_t{  /* A node along the path.  This could be the final node, one of its     parents, or the root.  Every parent path ends with an element for     the root directory.  */  dag_node_t *node;  /* The name NODE has in its parent directory.  This is zero for the     root directory, which (obviously) has no name in its parent.  */  char *entry;  /* The parent of NODE, or zero if NODE is the root directory.  */  struct parent_path_t *parent;  /* The copy ID inheritence style. */  copy_id_inherit_t copy_inherit;  /* If copy ID inheritence style is copy_id_inherit_new, this is the     path which should be implicitly copied; otherwise, this is NULL. */  const char *copy_src_path;} parent_path_t;static const char *parent_path_path(parent_path_t *parent_path,                 apr_pool_t *pool){  const char *path_so_far = "/";  if (parent_path->parent)    path_so_far = parent_path_path(parent_path->parent, pool);  return parent_path->entry    ? svn_path_join(path_so_far, parent_path->entry, pool)         : path_so_far;}/* Choose a copy ID inheritance method *INHERIT_P to be used in the   event that immutable node CHILD in FS needs to be made mutable.  If   the inheritance method is copy_id_inherit_new, also return a   *COPY_SRC_PATH on which to base the new copy ID (else return NULL   for that path).  CHILD must have a parent (it cannot be the root   node).  TXN_ID is the transaction in which these items might be   mutable.  */static svn_error_t *get_copy_inheritance(copy_id_inherit_t *inherit_p,                     const char **copy_src_path,                     svn_fs_t *fs,                     parent_path_t *child,                     const char *txn_id,                     trail_t *trail,                     apr_pool_t *pool){  const svn_fs_id_t *child_id, *parent_id;  const char *child_copy_id, *parent_copy_id;  const char *id_path = NULL;  /* Make some assertions about the function input. */  assert(child && child->parent && txn_id);  /* Initialize our return variables (default: self-inheritance). */  *inherit_p = copy_id_inherit_self;  *copy_src_path = NULL;  /* Initialize some convenience variables. */  child_id = svn_fs_base__dag_get_id(child->node);  parent_id = svn_fs_base__dag_get_id(child->parent->node);  child_copy_id = svn_fs_base__id_copy_id(child_id);  parent_copy_id = svn_fs_base__id_copy_id(parent_id);  /* Easy out: if this child is already mutable, we have nothing to do. */  if (svn_fs_base__key_compare(svn_fs_base__id_txn_id(child_id), txn_id) == 0)    return SVN_NO_ERROR;  /* If the child and its parent are on the same branch, then the     child will inherit the copy ID of its parent when made mutable.     This is trivially detectable when the child and its parent have     the same copy ID.  But that's not the sole indicator of     same-branchness.  It might be the case that the parent was the     result of a copy, but the child has not yet been cloned for     mutability since that copy.  Detection of this latter case     basically means making sure the copy IDs don't differ for some     other reason, such as that the child was the direct target of the     copy whose ID it has.  There is a special case here, too -- if     the child's copy ID is the special ID "0", it can't have been the     target of any copy, and therefore must be on the same branch as     its parent.  */  if ((strcmp(child_copy_id, "0") == 0)      || (svn_fs_base__key_compare(child_copy_id, parent_copy_id) == 0))    {      *inherit_p = copy_id_inherit_parent;      return SVN_NO_ERROR;    }  else    {      copy_t *copy;      SVN_ERR(svn_fs_bdb__get_copy(&copy, fs, child_copy_id, trail, pool));      if (svn_fs_base__id_compare(copy->dst_noderev_id, child_id) == -1)        {          *inherit_p = copy_id_inherit_parent;          return SVN_NO_ERROR;        }    }  /* If we get here, the child and its parent are not on speaking     terms -- there will be no parental inheritence handed down in     *this* generation. */  /* If the child was created at a different path than the one we are     expecting its clone to live, one of its parents must have been     created via a copy since the child was created.  The child isn't     on the same branch as its parent (we caught those cases early);     it can't keep its current copy ID because there's been an     affecting copy (its clone won't be on the same branch as the     child is).  That leaves only one course of action -- to assign     the child a brand new "soft" copy ID. */  id_path = svn_fs_base__dag_get_created_path(child->node);  if (strcmp(id_path, parent_path_path(child, pool)) != 0)    {      *inherit_p = copy_id_inherit_new;      *copy_src_path = id_path;      return SVN_NO_ERROR;    }  /* The node gets to keep its own ID. */  return SVN_NO_ERROR;}/* Allocate a new parent_path_t node from POOL, referring to NODE,   ENTRY, PARENT, and COPY_ID.  */static parent_path_t *make_parent_path(dag_node_t *node,                 char *entry,                 parent_path_t *parent,                 apr_pool_t *pool){  parent_path_t *parent_path = apr_pcalloc(pool, sizeof(*parent_path));  parent_path->node = node;  parent_path->entry = entry;  parent_path->parent = parent;  parent_path->copy_inherit = copy_id_inherit_unknown;  parent_path->copy_src_path = NULL;  return parent_path;}/* Return a null-terminated copy of the first component of PATH,   allocated in POOL.  If path is empty, or consists entirely of   slashes, return the empty string.   If the component is followed by one or more slashes, we set *NEXT_P   to point after the slashes.  If the component ends PATH, we set   *NEXT_P to zero.  This means:   - If *NEXT_P is zero, then the component ends the PATH, and there     are no trailing slashes in the path.   - If *NEXT_P points at PATH's terminating null character, then     the component returned was the last, and PATH ends with one or more     slash characters.   - Otherwise, *NEXT_P points to the beginning of the next component     of PATH.  You can pass this value to next_entry_name to extract     the next component.  */static char *next_entry_name(const char **next_p,                const char *path,                apr_pool_t *pool){  const char *end;  /* Find the end of the current component.  */  end = strchr(path, '/');  if (! end)    {      /* The path contains only one component, with no trailing         slashes.  */      *next_p = 0;      return apr_pstrdup(pool, path);    }  else    {      /* There's a slash after the first component.  Skip over an arbitrary         number of slashes to find the next one.  */      const char *next = end;      while (*next == '/')        next++;      *next_p = next;      return apr_pstrndup(pool, path, end - path);    }}/* Flags for open_path.  */typedef enum open_path_flags_t {  /* The last component of the PATH need not exist.  (All parent     directories must exist, as usual.)  If the last component doesn't     exist, simply leave the `node' member of the bottom parent_path     component zero.  */  open_path_last_optional = 1} open_path_flags_t;/* Open the node identified by PATH in ROOT, as part of TRAIL.  Set   *PARENT_PATH_P to a path from the node up to ROOT, allocated in   TRAIL->pool.  The resulting *PARENT_PATH_P value is guaranteed to   contain at least one element, for the root directory.   If resulting *PARENT_PATH_P will eventually be made mutable and   modified, or if copy ID inheritance information is otherwise   needed, TXN_ID should be the ID of the mutability transaction.  If   TXN_ID is NULL, no copy ID in heritance information will be   calculated for the *PARENT_PATH_P chain.   If FLAGS & open_path_last_optional is zero, return the error   SVN_ERR_FS_NOT_FOUND if the node PATH refers to does not exist.  If   non-zero, require all the parent directories to exist as normal,   but if the final path component doesn't exist, simply return a path   whose bottom `node' member is zero.  This option is useful for   callers that create new nodes --- we find the parent directory for   them, and tell them whether the entry exists already.   NOTE: Public interfaces which only *read* from the filesystem   should not call this function directly, but should instead use   get_dag().*/static svn_error_t *open_path(parent_path_t **parent_path_p,          svn_fs_root_t *root,          const char *path,          int flags,          const char *txn_id,          trail_t *trail,          apr_pool_t *pool){  svn_fs_t *fs = root->fs;  const svn_fs_id_t *id;  dag_node_t *here; /* The directory we're currently looking at.  */  parent_path_t *parent_path; /* The path from HERE up to the root.  */  const char *rest; /* The portion of PATH we haven't traversed yet.  */  const char *canon_path = svn_fs_base__canonicalize_abspath(path, pool);  const char *path_so_far = "/";  /* Make a parent_path item for the root node, using its own current     copy id.  */  SVN_ERR(root_node(&here, root, trail, pool));  id = svn_fs_base__dag_get_id(here);  parent_path = make_parent_path(here, 0, 0, pool);  parent_path->copy_inherit = copy_id_inherit_self;  rest = canon_path + 1; /* skip the leading '/', it saves in iteration */  /* Whenever we are at the top of this loop:     - HERE is our current directory,     - ID is the node revision ID of HERE,     - REST is the path we're going to find in HERE, and     - PARENT_PATH includes HERE and all its parents.  */  for (;;)    {      const char *next;      char *entry;      dag_node_t *child;      /* Parse out the next entry from the path.  */      entry = next_entry_name(&next, rest, pool);      /* Calculate the path traversed thus far. */      path_so_far = svn_path_join(path_so_far, entry, pool);      if (*entry == '\0')        {          /* Given the behavior of next_entry_name, this happens when             the path either starts or ends with a slash.  In either             case, we stay put: the current directory stays the same,             and we add nothing to the parent path.  */          child = here;        }      else        {          copy_id_inherit_t inherit;          const char *copy_path = NULL;          svn_error_t *err = SVN_NO_ERROR;          dag_node_t *cached_node;          /* If we found a directory entry, follow it.  First, we             check our node cache, and, failing that, we hit the DAG             layer. */          cached_node = dag_node_cache_get(root, path_so_far, pool);          if (cached_node)            child = cached_node;          else            err = svn_fs_base__dag_open(&child, here, entry, trail, pool);          /* "file not found" requires special handling.  */          if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)            {              /* If this was the last path component, and the caller                 said it was optional, then don't return an error;                 just put a NULL node pointer in the path.  */              svn_error_clear(err);              if ((flags & open_path_last_optional)                  && (! next || *next == '\0'))                {                  parent_path = make_parent_path(NULL, entry, parent_path,                                                 pool);                  break;                }              else                {                  /* Build a better error message than svn_fs_base__dag_open                     can provide, giving the root and full path name.  */                  return NOT_FOUND(root, path);                }            }          /* Other errors we return normally.  */          SVN_ERR(err);          /* Now, make a parent_path item for CHILD. */

⌨️ 快捷键说明

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