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

📄 status.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 5 页
字号:
                svn_wc_status_func_t status_func,
                void *status_baton,
                svn_cancel_func_t cancel_func,
                void *cancel_baton,
                apr_pool_t *pool)
{
  apr_hash_t *entries;
  apr_hash_index_t *hi;
  const svn_wc_entry_t *dir_entry;
  const char *fullpath, *path = svn_wc_adm_access_path (adm_access);
  apr_hash_t *dirents;
  apr_array_header_t *patterns = NULL;
  apr_pool_t *iterpool, *subpool = svn_pool_create (pool);

  /* See if someone wants to cancel this operation. */
  if (cancel_func)
    SVN_ERR (cancel_func (cancel_baton));

  /* Load entries file for the directory into the requested pool. */
  SVN_ERR (svn_wc_entries_read (&entries, adm_access, FALSE, subpool));

  /* Read PATH's dirents. */
  SVN_ERR (svn_io_get_dirents (&dirents, path, subpool));

  /* Get this directory's entry. */
  SVN_ERR (svn_wc_entry (&dir_entry, path, adm_access, FALSE, subpool));

  /* Unless specified, add default ignore regular expressions and try
     to add any svn:ignore properties from the parent directory. */
  if (ignores)
    {
      patterns = apr_array_make (subpool, 1, sizeof (const char *));
      SVN_ERR (collect_ignore_patterns (patterns, ignores, 
                                        adm_access, subpool));
    }

  /* If "this dir" has "svn:externals" property set on it, store its
     name and value in traversal_info.  Also, we want to track the
     externals internally so we can report status more accurately. */
  if (eb->traversal_info)
    {
      const svn_string_t *prop_val;
      SVN_ERR (svn_wc_prop_get (&prop_val, SVN_PROP_EXTERNALS, path, 
                                adm_access, subpool));
      if (prop_val)
        {
          apr_pool_t *dup_pool = eb->traversal_info->pool;
          const char *dup_path = apr_pstrdup (dup_pool, path);
          const char *dup_val = apr_pstrmemdup (dup_pool, prop_val->data, 
                                                prop_val->len);
          apr_array_header_t *ext_items;
          int i;

          /* First things first -- we put the externals information
             into the "global" traversal info structure. */
          apr_hash_set (eb->traversal_info->externals_old,
                        dup_path, APR_HASH_KEY_STRING, dup_val);
          apr_hash_set (eb->traversal_info->externals_new,
                        dup_path, APR_HASH_KEY_STRING, dup_val);

          /* Now, parse the thing, and copy the parsed results into
             our "global" externals hash. */
          SVN_ERR (svn_wc_parse_externals_description2 (&ext_items, path,
                                                        dup_val, dup_pool));
          for (i = 0; ext_items && i < ext_items->nelts; i++)
            {
              svn_wc_external_item_t *item;

              item = APR_ARRAY_IDX (ext_items, i, svn_wc_external_item_t *);
              apr_hash_set (eb->externals, svn_path_join (path,
                                                          item->target_dir,
                                                          dup_pool),
                            APR_HASH_KEY_STRING, item);
            }
        }
    }

  /* Early out -- our caller only cares about a single ENTRY in this
     directory.  */
  if (entry)
    {
      const svn_wc_entry_t *entry_entry;
      entry_entry = apr_hash_get (entries, entry, APR_HASH_KEY_STRING);

      /* If ENTRY is versioned, send its versioned status. */
      if (entry_entry)
        {
          SVN_ERR (handle_dir_entry (eb, adm_access, entry, dir_entry, 
                                     entry_entry, ignores, descend, get_all, 
                                     no_ignore, status_func, status_baton, 
                                     cancel_func, cancel_baton, subpool));
        }
      /* Otherwise, if it exists, send its unversioned status. */
      else if (apr_hash_get (dirents, entry, APR_HASH_KEY_STRING))
        {
          svn_node_kind_t kind;
          fullpath = svn_path_join (path, entry, subpool);
          SVN_ERR (svn_io_check_path (path, &kind, subpool));
          SVN_ERR (send_unversioned_item (entry, kind, adm_access, 
                                          patterns, eb->externals, no_ignore, 
                                          status_func, status_baton, subpool));
        }

      /* Regardless, we're done here.  Let's go home. */
      return SVN_NO_ERROR;
    }

  /** If we get here, ENTRY is NULL and we are handling all the
      directory entries. */

  /* Make our iteration pool. */
  iterpool = svn_pool_create (subpool);

  /* Add empty status structures for each of the unversioned things. */
  for (hi = apr_hash_first (subpool, dirents); hi; hi = apr_hash_next (hi))
    {
      const void *key;
      apr_ssize_t klen;
      void *val;
      svn_node_kind_t *path_kind;

      apr_hash_this (hi, &key, &klen, &val);
        
      /* Skip versioned things, and skip the administrative
         directory. */
      if ((apr_hash_get (entries, key, klen)) 
          || (strcmp (key, SVN_WC_ADM_DIR_NAME) == 0))
        continue;

      /* Clear the iteration subpool. */
      svn_pool_clear (iterpool);

      /* Make an unversioned status item for KEY, and put it into our
         return hash. */
      path_kind = val;
      SVN_ERR (send_unversioned_item (key, *path_kind, adm_access, 
                                      patterns, eb->externals, no_ignore, 
                                      status_func, status_baton, iterpool));
    }

  /* Handle "this-dir" first. */
  if (! skip_this_dir)
    SVN_ERR (send_status_structure (path, adm_access, dir_entry, 
                                    parent_entry, svn_node_dir,
                                    get_all, FALSE, status_func, 
                                    status_baton, subpool));

  /* Loop over entries hash */
  for (hi = apr_hash_first (pool, entries); hi; hi = apr_hash_next (hi))
    {
      const void *key;
      void *val;

      /* Get the next dirent */
      apr_hash_this (hi, &key, NULL, &val);

      /* ### todo: What if the subdir is from another repository? */
          
      /* Skip "this-dir". */
      if (strcmp (key, SVN_WC_ENTRY_THIS_DIR) == 0)
        continue;

      /* Clear the iteration subpool. */
      svn_pool_clear (iterpool);

      /* Handle this directory entry (possibly recursing). */
      SVN_ERR (handle_dir_entry (eb, adm_access, key, dir_entry, val, ignores, 
                                 descend, get_all, no_ignore, 
                                 status_func, status_baton, cancel_func, 
                                 cancel_baton, iterpool));
    }
  
  /* Destroy our subpools. */
  svn_pool_destroy (subpool);

  return SVN_NO_ERROR;
}



/*** Helpers ***/

/* A faux status callback function for stashing STATUS item in an hash
   (which is the BATON), keyed on PATH.  This implements the
   svn_wc_status_func_t interface. */
static void
hash_stash (void *baton,
            const char *path,
            svn_wc_status_t *status)
{
  apr_hash_t *stat_hash = baton;
  apr_pool_t *hash_pool = apr_hash_pool_get (stat_hash);
  assert (! apr_hash_get (stat_hash, path, APR_HASH_KEY_STRING));
  apr_hash_set (stat_hash, apr_pstrdup (hash_pool, path), 
                APR_HASH_KEY_STRING, svn_wc_dup_status (status, hash_pool));
}


/* Look up the key PATH in STATUSHASH.  If the value doesn't yet
   exist, and the REPOS_TEXT_STATUS indicates that this is an
   addition, create a new status struct using the hash's pool.  Merge
   REPOS_TEXT_STATUS and REPOS_PROP_STATUS into the status structure's
   "network" fields. */
static svn_error_t *
tweak_statushash (apr_hash_t *statushash,
                  svn_wc_adm_access_t *adm_access,
                  const char *path,
                  svn_boolean_t is_dir,
                  enum svn_wc_status_kind repos_text_status,
                  enum svn_wc_status_kind repos_prop_status)
{
  svn_wc_status_t *statstruct;
  apr_pool_t *pool = apr_hash_pool_get (statushash);

  /* Is PATH already a hash-key? */
  statstruct = apr_hash_get (statushash, path, APR_HASH_KEY_STRING);

  /* If not, make it so. */
  if (! statstruct)
    {
      /* This should only be missing from the hash if it's being added
         from the repository status drive. */
      assert (repos_text_status == svn_wc_status_added);

      /* Use the public API to get a statstruct, and put it into the hash. */
      SVN_ERR (svn_wc_status (&statstruct, path, NULL, pool));
      apr_hash_set (statushash, apr_pstrdup (pool, path), 
                    APR_HASH_KEY_STRING, statstruct);
    }

  /* Merge a repos "delete" + "add" into a single "replace". */
  if ((repos_text_status == svn_wc_status_added)
      && (statstruct->repos_text_status == svn_wc_status_deleted))
    repos_text_status = svn_wc_status_replaced;

  /* Tweak the structure's repos fields. */
  if (repos_text_status)
    statstruct->repos_text_status = repos_text_status;
  if (repos_prop_status)
    statstruct->repos_prop_status = repos_prop_status;
  
  return SVN_NO_ERROR;
}



/* Create a new dir_baton for subdir PATH. */
static svn_error_t *
make_dir_baton (void **dir_baton,
                const char *path,
                struct edit_baton *edit_baton,
                struct dir_baton *parent_baton,
                apr_pool_t *pool)
{
  struct dir_baton *pb = parent_baton;
  struct edit_baton *eb = edit_baton;
  struct dir_baton *d = apr_pcalloc (pool, sizeof (*d));
  const char *full_path; 
  svn_wc_status_t *parent_status;

  /* Don't do this.  Just do NOT do this to me. */
  if (pb && (! path))
    abort();

  /* Construct the full path of this directory. */
  if (pb)
    full_path = svn_path_join (eb->anchor, path, pool);
  else
    full_path = apr_pstrdup (pool, eb->anchor);

  /* Finish populating the baton members. */
  d->path         = full_path;
  d->name         = path ? (svn_path_basename (path, pool)) : NULL;
  d->edit_baton   = edit_baton;
  d->parent_baton = parent_baton;
  d->pool         = pool;
  d->statii       = apr_hash_make (pool);

  /* Get the status for this path's children.  Of course, we only want
     to do this if the path is versioned as a directory. */
  if (pb)
    parent_status = apr_hash_get (pb->statii, d->path, APR_HASH_KEY_STRING);
  else
    parent_status = eb->anchor_status;
  if (parent_status
      && (parent_status->text_status != svn_wc_status_unversioned)
      && (parent_status->text_status != svn_wc_status_deleted)
      && (parent_status->text_status != svn_wc_status_missing)
      && (parent_status->text_status != svn_wc_status_obstructed)
      && (parent_status->entry->kind == svn_node_dir)
      && (eb->descend || (! pb)))
    {
      svn_wc_adm_access_t *dir_access;
      apr_array_header_t *ignores = eb->ignores;
      SVN_ERR (svn_wc_adm_retrieve (&dir_access, eb->adm_access, 
                                    d->path, pool));
      SVN_ERR (get_dir_status (eb, parent_status->entry, dir_access, NULL, 
                               ignores, FALSE, TRUE, TRUE, TRUE, hash_stash, 
                               d->statii, NULL, NULL, pool));
    }

  *dir_baton = d;
  return SVN_NO_ERROR;
}


/* Make a file baton, using a new subpool of PARENT_DIR_BATON's pool.
   NAME is just one component, not a path. */
static struct file_baton *
make_file_baton (struct dir_baton *parent_dir_baton, 
                 const char *path,
                 apr_pool_t *pool)
{
  struct dir_baton *pb = parent_dir_baton;
  struct edit_baton *eb = pb->edit_baton;
  struct file_baton *f = apr_pcalloc (pool, sizeof (*f));
  const char *full_path;
 
  /* Construct the full path of this directory. */
  if (pb)
    full_path = svn_path_join (eb->anchor, path, pool);
  else
    full_path = apr_pstrdup (pool, eb->anchor);

  /* Finish populating the baton members. */
  f->path       = full_path;
  f->name       = svn_path_basename (path, pool);
  f->pool       = pool;
  f->dir_baton  = pb;
  f->edit_baton = eb;

  return f;
}


/* Return a boolean answer to the question "Is STATUS something that
   should be reported?".  EB is the edit baton. */
static svn_boolean_t 
is_sendable_status (svn_wc_status_t *status,
                    struct edit_baton *eb)
{
  /* If the repository status was touched at all, it's interesting. */
  if (status->repos_text_status != svn_wc_status_none)
    return TRUE;
  if (status->repos_prop_status != svn_wc_status_none)
    return TRUE;

⌨️ 快捷键说明

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