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

📄 entries.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
      }  }    /* cachable-props string. */  entry->cachable_props = apr_hash_get(atts,                                        SVN_WC__ENTRY_ATTR_CACHABLE_PROPS,                                       APR_HASH_KEY_STRING);  if (entry->cachable_props)    {      *modify_flags |= SVN_WC__ENTRY_MODIFY_CACHABLE_PROPS;      entry->cachable_props = apr_pstrdup(pool, entry->cachable_props);    }  /* present-props string. */  entry->present_props = apr_hash_get(atts,                                       SVN_WC__ENTRY_ATTR_PRESENT_PROPS,                                      APR_HASH_KEY_STRING);  if (entry->present_props)    {      *modify_flags |= SVN_WC__ENTRY_MODIFY_PRESENT_PROPS;      entry->present_props = apr_pstrdup(pool, entry->present_props);    }  *new_entry = entry;  return SVN_NO_ERROR;}/* Used when reading an entries file in XML format. */struct entries_accumulator{  /* Keys are entry names, vals are (struct svn_wc_entry_t *)'s. */  apr_hash_t *entries;   /* The parser that's parsing it, for signal_expat_bailout(). */  svn_xml_parser_t *parser;  /* Should we include 'deleted' entries in the hash? */  svn_boolean_t show_hidden;  /* Don't leave home without one. */  apr_pool_t *pool;  /* Cleared before handling each entry. */  apr_pool_t *scratch_pool;};/* Called whenever we find an <open> tag of some kind. */static voidhandle_start_tag(void *userData, const char *tagname, const char **atts){  struct entries_accumulator *accum = userData;  apr_hash_t *attributes;  svn_wc_entry_t *entry;  svn_error_t *err;  apr_uint32_t modify_flags = 0;  /* We only care about the `entry' tag; all other tags, such as `xml'     and `wc-entries', are ignored. */  if (strcmp(tagname, SVN_WC__ENTRIES_ENTRY))    return;  svn_pool_clear(accum->scratch_pool);  /* Make an entry from the attributes. */  attributes = svn_xml_make_att_hash(atts, accum->scratch_pool);  err = svn_wc__atts_to_entry(&entry, &modify_flags, attributes, accum->pool);  if (err)    {      svn_xml_signal_bailout(err, accum->parser);      return;    }          /* Find the name and set up the entry under that name.  This     should *NOT* be NULL, since svn_wc__atts_to_entry() should     have made it into SVN_WC_ENTRY_THIS_DIR.  (Note that technically,     an entry can't be both absent and scheduled for addition, but we     don't need a sanity check for that here.) */  if ((entry->deleted || entry->absent)      && (entry->schedule != svn_wc_schedule_add)      && (entry->schedule != svn_wc_schedule_replace)      && (! accum->show_hidden))    ;  else    apr_hash_set(accum->entries, entry->name, APR_HASH_KEY_STRING, entry);}/* Parse BUF of size SIZE as an entries file in XML format, storing the parsed   entries in ENTRIES.  Use pool for temporary allocations and the pool of   ADM_ACCESS for the returned entries. */static svn_error_t *parse_entries_xml(svn_wc_adm_access_t *adm_access,                  apr_hash_t *entries,                  svn_boolean_t show_hidden,                  const char *buf,                  apr_size_t size,                  apr_pool_t *pool){  svn_xml_parser_t *svn_parser;  struct entries_accumulator accum;  /* Set up userData for the XML parser. */  accum.entries = entries;  accum.show_hidden = show_hidden;  accum.pool = svn_wc_adm_access_pool(adm_access);  accum.scratch_pool = svn_pool_create(pool);  /* Create the XML parser */  svn_parser = svn_xml_make_parser(&accum,                                   handle_start_tag,                                   NULL,                                   NULL,                                   pool);  /* Store parser in its own userdata, so callbacks can call     svn_xml_signal_bailout() */  accum.parser = svn_parser;  /* Parse. */  SVN_ERR_W(svn_xml_parse(svn_parser, buf, size, TRUE),            apr_psprintf(pool,                         _("XML parser failed in '%s'"),                         svn_path_local_style                         (svn_wc_adm_access_path(adm_access), pool)));  svn_pool_destroy(accum.scratch_pool);  /* Clean up the XML parser */  svn_xml_free_parser(svn_parser);  return SVN_NO_ERROR;}/* Use entry SRC to fill in blank portions of entry DST.  SRC itself   may not have any blanks, of course.   Typically, SRC is a parent directory's own entry, and DST is some   child in that directory. */static voidtake_from_entry(svn_wc_entry_t *src, svn_wc_entry_t *dst, apr_pool_t *pool){  /* Inherits parent's revision if doesn't have a revision of one's     own, unless this is a subdirectory. */  if ((dst->revision == SVN_INVALID_REVNUM) && (dst->kind != svn_node_dir))    dst->revision = src->revision;    /* Inherits parent's url if doesn't have a url of one's own. */  if (! dst->url)     dst->url = svn_path_url_add_component(src->url, dst->name, pool);  if (! dst->repos)    dst->repos = src->repos;  if ((! dst->uuid)       && (! ((dst->schedule == svn_wc_schedule_add)             || (dst->schedule == svn_wc_schedule_replace))))    {      dst->uuid = src->uuid;    }  if (! dst->cachable_props)    dst->cachable_props = src->cachable_props;}/* Resolve any missing information in ENTRIES by deducing from the   directory's own entry (which must already be present in ENTRIES). */static svn_error_t *resolve_to_defaults(apr_hash_t *entries,                    apr_pool_t *pool){  apr_hash_index_t *hi;  svn_wc_entry_t *default_entry    = apr_hash_get(entries, SVN_WC_ENTRY_THIS_DIR, APR_HASH_KEY_STRING);  /* First check the dir's own entry for consistency. */  if (! default_entry)    return svn_error_create(SVN_ERR_ENTRY_NOT_FOUND,                            NULL,                            _("Missing default entry"));  if (default_entry->revision == SVN_INVALID_REVNUM)    return svn_error_create(SVN_ERR_ENTRY_MISSING_REVISION,                            NULL,                            _("Default entry has no revision number"));  if (! default_entry->url)    return svn_error_create(SVN_ERR_ENTRY_MISSING_URL,                            NULL,                            _("Default entry is missing URL"));        /* Then use it to fill in missing information in other entries. */  for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))    {      void *val;      svn_wc_entry_t *this_entry;      apr_hash_this(hi, NULL, NULL, &val);      this_entry = val;      if (this_entry == default_entry)         /* THIS_DIR already has all the information it can possibly           have.  */        continue;      if (this_entry->kind == svn_node_dir)        /* Entries that are directories have everything but their           name, kind, and state stored in the THIS_DIR entry of the           directory itself.  However, we are disallowing the perusing           of any entries outside of the current entries file.  If a           caller wants more info about a directory, it should look in           the entries file in the directory.  */        continue;      if (this_entry->kind == svn_node_file)        /* For file nodes that do not explicitly have their ancestry           stated, this can be derived from the default entry of the           directory in which those files reside.  */        take_from_entry(default_entry, this_entry, pool);    }  return SVN_NO_ERROR;}/* Fill the entries cache in ADM_ACCESS. Either the full hash cache will be   populated, if SHOW_HIDDEN is TRUE, or the truncated hash cache will be   populated if SHOW_HIDDEN is FALSE.  POOL is used for local memory   allocation, the access baton pool is used for the cache. */static svn_error_t *read_entries(svn_wc_adm_access_t *adm_access,             svn_boolean_t show_hidden,             apr_pool_t *pool){  const char *path = svn_wc_adm_access_path(adm_access);  apr_file_t *infile = NULL;  svn_stringbuf_t *buf = svn_stringbuf_create("", pool);  apr_hash_t *entries = apr_hash_make(svn_wc_adm_access_pool(adm_access));  char *curp, *endp;  svn_wc_entry_t *entry;  int entryno;  /* Open the entries file. */  SVN_ERR(svn_wc__open_adm_file(&infile, path,                                SVN_WC__ADM_ENTRIES, APR_READ, pool));  SVN_ERR(svn_stringbuf_from_aprfile(&buf, infile, pool));  curp = buf->data;  endp = buf->data + buf->len;  /* If the first byte of the file is not a digit, then it is probably in XML     format. */  if (curp != endp && !svn_ctype_isdigit(*curp))    SVN_ERR(parse_entries_xml(adm_access, entries, show_hidden,                              buf->data, buf->len, pool));  else    {      /* Skip format line. */      /* ### Could read it here and report it to caller if it wants it. */      curp = memchr(curp, '\n', buf->len);      if (! curp)        return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,                                 _("Invalid version line in entries file "                                   "of '%s'"),                                 svn_path_local_style(path, pool));      ++curp;      entryno = 1;      while (curp != endp)        {          svn_error_t *err = read_entry(&entry, &curp, endp,                                        svn_wc_adm_access_pool(adm_access));          if (! err)            {              /* We allow extra fields at the end of the line, for                 extensibility. */              curp = memchr(curp, '\f', endp - curp);              if (! curp)                err = svn_error_create(SVN_ERR_WC_CORRUPT, NULL,                                       _("Missing entry terminator"));              if (! err && (curp == endp || *(++curp) != '\n'))                err = svn_error_create(SVN_ERR_WC_CORRUPT, NULL,                                       _("Invalid entry terminator"));            }          if (err)            return svn_error_createf(err->apr_err, err,                                     _("Error at entry %d in entries file for "                                       "'%s':"),                                     entryno, svn_path_local_style(path, pool));                ++curp;          ++entryno;          if ((entry->deleted || entry->absent)              && (entry->schedule != svn_wc_schedule_add)              && (entry->schedule != svn_wc_schedule_replace)              && (! show_hidden))            ;          else            apr_hash_set(entries, entry->name, APR_HASH_KEY_STRING, entry);        }    }  /* Close the entries file. */  SVN_ERR(svn_wc__close_adm_file(infile, svn_wc_adm_access_path(adm_access),                                 SVN_WC__ADM_ENTRIES, 0, pool));  /* Fill in any implied fields. */  SVN_ERR(resolve_to_defaults(entries, svn_wc_adm_access_pool(adm_access)));  svn_wc__adm_access_set_entries(adm_access, show_hidden, entries);  return SVN_NO_ERROR;}/* For non-directory PATHs full entry information is obtained by reading * the entries for the parent directory of PATH and then extracting PATH's * entry.  If PATH is a directory then only abrieviated information is * available in the parent directory, more complete information is * available by reading the entries for PATH itself. * * Note: There is one bit of information about directories that is only * available in the parent directory, that is the "deleted" state.  If PATH * is a versioned directory then the "deleted" state information will not * be returned in ENTRY.  This means some bits of the code (e.g. revert) * need to obtain it by directly extracting the directory entry from the * parent directory's entries.  I wonder if this function should handle * that? */svn_error_t *svn_wc_entry(const svn_wc_entry_t **entry,             const char *path,             svn_wc_adm_access_t *adm_access,             svn_boolean_t show_hidden,             apr_pool_t *pool){  const char *entry_name;  svn_wc_adm_access_t *dir_access;  SVN_ERR(svn_wc__adm_retrieve_internal(&dir_access, adm_access, path, pool));  if (! dir_access)    {      const char *dir_path, *base_name;      svn_path_split(path, &dir_path, &base_name, pool);      SVN_ERR(svn_wc__adm_retrieve_internal(&dir_access, adm_access, dir_path,                                            pool));      entry_name = base_name;    }  else    entry_name = SVN_WC_ENTRY_THIS_DIR;  if (dir_access)    {      apr_hash_t *entries;      SVN_ERR(svn_wc_entries_read(&entries, dir_access, show_hidden, pool));      *entry = apr_hash_get(entries, entry_name, APR_HASH_KEY_STRING);    }  else    *entry = NULL;  return SVN_NO_ERROR;}#if 0/* This is #if 0'd out until I decide where to use it. --cmpilato *//* Run a simple validity check on the ENTRIES (the list of entries   associated with the directory PATH). */static svn_error_t *check_entries(apr_hash_t *entries,              const char *path,              apr_pool_t *pool){  svn_wc_entry_t *default_entry;  apr_hash_index_t *hi;  default_entry = apr_hash_get(entries,                                SVN_WC_ENTRY_THIS_DIR,                                APR_HASH_KEY_STRING);  if (! default_entry)    return svn_error_createf      (SVN_ERR_WC_CORRUPT, NULL,       _("Corrupt working copy: '%s' has no default entry"),       svn_path_local_style(path, pool));  /* Validate DEFAULT_ENTRY's current schedule. */  switch (default_entry->schedule)    {    case svn_wc_schedule_normal:    case svn_wc_schedule_add:    case svn_wc_schedule_delete:    case svn_wc_schedule_replace:      /* These are all valid states */      break;    default:      /* This is an invalid state */      return svn_error_createf        (SVN_ERR_WC_CORRUPT, NULL,         _("Corrupt working copy: directory '%s' has an invalid schedule"),         svn_path_local_style(path, pool));    }

⌨️ 快捷键说明

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