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

📄 entries.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* Is this entry incomplete? */
  {
    const char *incompletestr;
      
    incompletestr = apr_hash_get (atts, SVN_WC__ENTRY_ATTR_INCOMPLETE, 
                                  APR_HASH_KEY_STRING);
        
    entry->incomplete = FALSE;
    if (incompletestr)
      {
        if (! strcmp (incompletestr, "true"))
          entry->incomplete = TRUE;
        else if (! strcmp (incompletestr, "false"))
          entry->incomplete = FALSE;
        else if (! strcmp (incompletestr, ""))
          entry->incomplete = FALSE;
        else
          return svn_error_createf 
            (SVN_ERR_ENTRY_ATTRIBUTE_INVALID, NULL,
             _("Entry '%s' has invalid '%s' value"),
             (name ? name : SVN_WC_ENTRY_THIS_DIR),
             SVN_WC__ENTRY_ATTR_INCOMPLETE);

        *modify_flags |= SVN_WC__ENTRY_MODIFY_INCOMPLETE;
      }
  }


  /* Attempt to set up timestamps. */
  {
    const char *text_timestr, *prop_timestr;
    
    text_timestr = apr_hash_get (atts, SVN_WC__ENTRY_ATTR_TEXT_TIME,
                                 APR_HASH_KEY_STRING);
    if (text_timestr)
      {
        if (! strcmp (text_timestr, SVN_WC_TIMESTAMP_WC))
          {
            /* Special case:  a magic string that means 'get this value
               from the working copy' -- we ignore it here, trusting
               that the caller of this function know what to do about
               it.  */
          }
        else
          SVN_ERR (svn_time_from_cstring (&entry->text_time, text_timestr,
                                          pool));
        
        *modify_flags |= SVN_WC__ENTRY_MODIFY_TEXT_TIME;
      }
    
    prop_timestr = apr_hash_get (atts, SVN_WC__ENTRY_ATTR_PROP_TIME,
                                 APR_HASH_KEY_STRING);
    if (prop_timestr)
      {
        if (! strcmp (prop_timestr, SVN_WC_TIMESTAMP_WC))
          {
            /* Special case:  a magic string that means 'get this value
               from the working copy' -- we ignore it here, trusting
               that the caller of this function know what to do about
               it.  */
          }
        else
          SVN_ERR (svn_time_from_cstring (&entry->prop_time, prop_timestr,
                                          pool));
        
        *modify_flags |= SVN_WC__ENTRY_MODIFY_PROP_TIME;
      }
  }

  /* Checksum. */
  {
    entry->checksum = apr_hash_get (atts, SVN_WC__ENTRY_ATTR_CHECKSUM,
                                    APR_HASH_KEY_STRING);
    if (entry->checksum)
      *modify_flags |= SVN_WC__ENTRY_MODIFY_CHECKSUM;
  }

  /* UUID. */
  {
    entry->uuid = apr_hash_get (atts, SVN_WC__ENTRY_ATTR_UUID,
                                APR_HASH_KEY_STRING);
    if (entry->uuid)
      *modify_flags |= SVN_WC__ENTRY_MODIFY_UUID;
  }

  /* Setup last-committed values. */
  {
    const char *cmt_datestr, *cmt_revstr;
    
    cmt_datestr = apr_hash_get (atts, SVN_WC__ENTRY_ATTR_CMT_DATE,
                                APR_HASH_KEY_STRING);
    if (cmt_datestr)
      {
        SVN_ERR (svn_time_from_cstring (&entry->cmt_date, cmt_datestr, pool));
        *modify_flags |= SVN_WC__ENTRY_MODIFY_CMT_DATE;
      }
    else
      entry->cmt_date = 0;

    cmt_revstr = apr_hash_get (atts, SVN_WC__ENTRY_ATTR_CMT_REV,
                               APR_HASH_KEY_STRING);
    if (cmt_revstr)
      {
        entry->cmt_rev = SVN_STR_TO_REV (cmt_revstr);
        *modify_flags |= SVN_WC__ENTRY_MODIFY_CMT_REV;
      }
    else
      entry->cmt_rev = SVN_INVALID_REVNUM;

    entry->cmt_author = apr_hash_get (atts, SVN_WC__ENTRY_ATTR_CMT_AUTHOR,
                                      APR_HASH_KEY_STRING);
    if (entry->cmt_author)
        *modify_flags |= SVN_WC__ENTRY_MODIFY_CMT_AUTHOR;
  }
  
  
  *new_entry = entry;
  return SVN_NO_ERROR;
}

                       

/* Called whenever we find an <open> tag of some kind. */
static void
handle_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;

  /* Make an entry from the attributes. */
  attributes = svn_xml_make_att_hash (atts, accum->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);
}


/* 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 void
take_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->uuid) 
      && (! ((dst->schedule == svn_wc_schedule_add)
             || (dst->schedule == svn_wc_schedule_replace))))
    {
      dst->uuid = src->uuid;
    }
}


/* 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)
{
  svn_error_t *err;
  svn_boolean_t is_final;
  apr_file_t *infile = NULL;
  svn_xml_parser_t *svn_parser;
  char buf[BUFSIZ];
  apr_size_t bytes_read;
  struct entries_accumulator accum;
  apr_hash_t *entries = apr_hash_make (svn_wc_adm_access_pool (adm_access));

  /* Open the entries file. */
  SVN_ERR (svn_wc__open_adm_file (&infile,
                                  svn_wc_adm_access_path (adm_access),
                                  SVN_WC__ADM_ENTRIES, APR_READ, pool));

  /* Set up userData for the XML parser. */
  accum.entries = entries;
  accum.show_hidden = show_hidden;
  accum.pool = svn_wc_adm_access_pool (adm_access);

  /* 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. */
  do {
    err = svn_io_file_read_full (infile, buf, sizeof(buf), &bytes_read, pool);
    if (err && !APR_STATUS_IS_EOF(err->apr_err))
      return err;

    is_final = (err != NULL); /* EOF is only possible error */
    svn_error_clear (err);
    
    SVN_ERR_W (svn_xml_parse (svn_parser, buf, bytes_read, is_final),
               apr_psprintf (pool,
                             _("XML parser failed in '%s'"),
                             svn_wc_adm_access_path (adm_access)));
  } while (! is_final);

  /* 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));

  /* Clean up the XML parser */
  svn_xml_free_parser (svn_parser);

  /* 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 */

⌨️ 快捷键说明

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