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

📄 adm_ops.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 5 页
字号:
                           SVN_WC__ENTRY_ATTR_CHECKSUM,
                           hex_digest,
                           NULL);

  /* Regardless of whether it's a file or dir, the "main" logfile
     contains a command to bump the revision attribute (and
     timestamp.)  */
  svn_xml_make_open_tag (&logtags, pool, svn_xml_self_closing,
                         SVN_WC__LOG_COMMITTED,
                         SVN_WC__LOG_ATTR_NAME, base_name,
                         SVN_WC__LOG_ATTR_REVISION, 
                         revstr,
                         NULL);


  /* Do wcprops in the same log txn as revision, etc. */
  if (wcprop_changes && (wcprop_changes->nelts > 0))
    {
      int i;

      for (i = 0; i < wcprop_changes->nelts; i++)
        {
          svn_prop_t *prop = APR_ARRAY_IDX (wcprop_changes, i, svn_prop_t *);

          svn_xml_make_open_tag (&logtags, pool, svn_xml_self_closing,
                                 SVN_WC__LOG_MODIFY_WCPROP,
                                 SVN_WC__LOG_ATTR_NAME,
                                 base_name,
                                 SVN_WC__LOG_ATTR_PROPNAME,
                                 prop->name,
                                 prop->value ? SVN_WC__LOG_ATTR_PROPVAL : NULL,
                                 prop->value ? prop->value->data : NULL,
                                 NULL);
        }
    }

  SVN_ERR_W (svn_io_file_write_full (log_fp, logtags->data, 
                                     logtags->len, NULL, pool),
             apr_psprintf (pool, _("Error writing log file for '%s'"), path));
      
  SVN_ERR (svn_wc__close_adm_file (log_fp, svn_wc_adm_access_path (adm_access),
                                   SVN_WC__ADM_LOG,
                                   TRUE, /* sync */
                                   pool));


  /* Run the log file we just created. */
  SVN_ERR (svn_wc__run_log (adm_access, NULL, pool));
            
  if (recurse)
    {
      apr_hash_t *entries;
      apr_hash_index_t *hi;
      apr_pool_t *subpool = svn_pool_create (pool);

      /* Read PATH's entries;  this is the absolute path. */
      SVN_ERR (svn_wc_entries_read (&entries, adm_access, TRUE, pool));

      /* Recursively loop over all children. */
      for (hi = apr_hash_first (pool, entries); hi; hi = apr_hash_next (hi))
        {
          const void *key;
          void *val;
          const char *name;
          const svn_wc_entry_t *current_entry;
          const char *this_path;
          svn_wc_adm_access_t *child_access;

          apr_hash_this (hi, &key, NULL, &val);
          name = key;
          current_entry = val;
          
          /* Ignore the "this dir" entry. */
          if (! strcmp (name, SVN_WC_ENTRY_THIS_DIR))
            continue;
          
          /* Create child path by telescoping the main path. */
          this_path = svn_path_join (path, name, subpool);

          if (current_entry->kind == svn_node_dir)
             SVN_ERR (svn_wc_adm_retrieve (&child_access, adm_access, this_path,
                                           subpool));
          else
             child_access = adm_access;
          
          /* Recurse, but only allow further recursion if the child is
             a directory.  Pass null for wcprop_changes, because the
             ones present in the current call are only applicable to
             this one committed item. */
          SVN_ERR (svn_wc_process_committed 
                   (this_path, child_access,
                    (current_entry->kind == svn_node_dir) ? TRUE : FALSE,
                    new_revnum, rev_date, rev_author, NULL, subpool));

          svn_pool_clear (subpool);
        }

      svn_pool_destroy (subpool); 
   }

  return SVN_NO_ERROR;
}




/* Remove FILE if it exists and is a file.  If it does not exist, do
   nothing.  If it is not a file, error. */
static svn_error_t *
remove_file_if_present (const char *file, apr_pool_t *pool)
{
  svn_node_kind_t kind;

  /* Does this file exist?  If not, get outta here. */
  SVN_ERR (svn_io_check_path (file, &kind, pool));
  if (kind == svn_node_none)
    return SVN_NO_ERROR;

  /* Else, remove the file. */
  return svn_io_remove_file (file, pool);
}




/* Recursively mark a tree ADM_ACCESS for with a SCHEDULE and/or EXISTENCE
   flag and/or COPIED flag, depending on the state of MODIFY_FLAGS. */
static svn_error_t *
mark_tree (svn_wc_adm_access_t *adm_access, 
           apr_uint32_t modify_flags,
           svn_wc_schedule_t schedule,
           svn_boolean_t copied,
           svn_cancel_func_t cancel_func,
           void *cancel_baton,
           svn_wc_notify_func_t notify_func,
           void *notify_baton,
           apr_pool_t *pool)
{
  apr_pool_t *subpool = svn_pool_create (pool);
  apr_hash_t *entries;
  apr_hash_index_t *hi;
  const svn_wc_entry_t *entry; 

  /* Read the entries file for this directory. */
  SVN_ERR (svn_wc_entries_read (&entries, adm_access, FALSE, pool));

  /* Mark each entry in the entries file. */
  for (hi = apr_hash_first (pool, entries); hi; hi = apr_hash_next (hi))
    {
      const char *fullpath;
      const void *key;
      void *val;
      const char *base_name;
      svn_wc_entry_t *dup_entry;

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

      /* Skip "this dir".  */
      if (! strcmp ((const char *)key, SVN_WC_ENTRY_THIS_DIR))
        continue;
          
      base_name = key;
      fullpath = svn_path_join (svn_wc_adm_access_path (adm_access), base_name,
                                subpool);

      /* If this is a directory, recurse. */
      if (entry->kind == svn_node_dir)
        {
          svn_wc_adm_access_t *child_access;
          SVN_ERR (svn_wc_adm_retrieve (&child_access, adm_access, fullpath,
                                        subpool));
          SVN_ERR (mark_tree (child_access, modify_flags,
                              schedule, copied,
                              cancel_func, cancel_baton,
                              notify_func, notify_baton,
                              subpool));
        }

      /* Need to duplicate the entry because we are changing the scheduling */
      dup_entry = svn_wc_entry_dup (entry, subpool);
      dup_entry->schedule = schedule;
      dup_entry->copied = copied; 
      SVN_ERR (svn_wc__entry_modify (adm_access, base_name, dup_entry, 
                                     modify_flags, TRUE, subpool));

      /* Tell someone what we've done. */
      if (schedule == svn_wc_schedule_delete && notify_func != NULL)
        (*notify_func) (notify_baton, fullpath, svn_wc_notify_delete,
                        svn_node_unknown,
                        NULL,
                        svn_wc_notify_state_unknown,
                        svn_wc_notify_state_unknown,
                        SVN_INVALID_REVNUM);

      /* Clear our per-iteration pool. */
      svn_pool_clear (subpool);
    }
  
  /* Handle "this dir" for states that need it done post-recursion. */
  entry = apr_hash_get (entries, SVN_WC_ENTRY_THIS_DIR, APR_HASH_KEY_STRING);

  /* Uncommitted directories (schedule add) that are to be scheduled for
     deletion are a special case, they don't need to be changed as they
     will be removed from their parent's entry list. */
  if (! (entry->schedule == svn_wc_schedule_add
         && schedule == svn_wc_schedule_delete))
  {
    /* Need to duplicate the entry because we are changing the scheduling */
    svn_wc_entry_t *dup_entry = svn_wc_entry_dup (entry, subpool);
    if (modify_flags & SVN_WC__ENTRY_MODIFY_SCHEDULE)
      dup_entry->schedule = schedule;
    if (modify_flags & SVN_WC__ENTRY_MODIFY_COPIED)
      dup_entry->copied = copied;
    SVN_ERR (svn_wc__entry_modify (adm_access, NULL, dup_entry, modify_flags,
                                   TRUE, subpool));
  }
  
  /* Destroy our per-iteration pool. */
  svn_pool_destroy (subpool);
  return SVN_NO_ERROR;
}

/* Remove/erase PATH from the working copy. This involves deleting PATH
 * from the physical filesystem. PATH is assumed to be an unversioned file
 * or directory.
 *
 * If CANCEL_FUNC is non-null, invoke it with CANCEL_BATON at various
 * points, return any error immediately.
 */
static svn_error_t *
erase_unversioned_from_wc (const char *path,
                           svn_cancel_func_t cancel_func,
                           void *cancel_baton,
                           apr_pool_t *pool)
{
  svn_node_kind_t kind;

  SVN_ERR (svn_io_check_path (path, &kind, pool));
  switch (kind)
    {
    case svn_node_none:
      /* Nothing to do. */
      break;

    default:
      /* ### TODO: what do we do here? To handle Unix symlinks we
         fallthrough to svn_node_file... gulp! */

    case svn_node_file:
      SVN_ERR (svn_io_remove_file (path, pool));
      break;

    case svn_node_dir:
      /* ### It would be more in the spirit of things to feed the
         ### cancellation check through to svn_io_remove_dir()... */
      if (cancel_func)
        SVN_ERR (cancel_func (cancel_baton));

      SVN_ERR (svn_io_remove_dir (path, pool));

      if (cancel_func)
        SVN_ERR (cancel_func (cancel_baton));

      break;
    }

  return SVN_NO_ERROR;
}

/* Remove/erase PATH from the working copy. For files this involves
 * deletion from the physical filesystem.  For directories it involves the
 * deletion from the filesystem of all unversioned children, and all
 * versioned children that are files. By the time we get here, added but
 * not committed items will have been scheduled for deletion which means
 * they have become unversioned.
 *
 * The result is that all that remains are versioned directories, each with
 * its .svn directory and .svn contents.
 *
 * If CANCEL_FUNC is non-null, invoke it with CANCEL_BATON at various
 * points, return any error immediately.
 *
 * KIND is the node kind appropriate for PATH
 */
static svn_error_t *
erase_from_wc (const char *path,
               svn_wc_adm_access_t *adm_access,
               svn_node_kind_t kind,
               svn_cancel_func_t cancel_func,
               void *cancel_baton,
               apr_pool_t *pool)
{
  /* Check that the item exists in the wc. */
  svn_node_kind_t wc_kind;
  SVN_ERR (svn_io_check_path (path, &wc_kind, pool));
  if (wc_kind == svn_node_none)
    return SVN_NO_ERROR;

  if (cancel_func)
    SVN_ERR (cancel_func (cancel_baton));

  switch (kind)
    {
    default:
      /* ### TODO: what do we do here? */
      break;

    case svn_node_file:
      SVN_ERR (svn_io_remove_file (path, pool));
      break;

    case svn_node_dir:
      {
        apr_hash_t *ver, *unver;
        apr_hash_index_t *hi;
        svn_wc_adm_access_t *dir_access;

        /* ### Suspect that an iteration or recursion subpool would be
           good here. */

        /* First handle the versioned items, this is better (probably) than
           simply using svn_io_get_dirents for everything as it avoids the
           need to do svn_io_check_path on each versioned item */
        SVN_ERR (svn_wc_adm_retrieve (&dir_access, adm_access, path, pool));
        SVN_ERR (svn_wc_entries_read (&ver, dir_access, FALSE, pool));
        for (hi = apr_hash_first (pool, ver); hi; hi = apr_hash_next (hi))
          {
            const void *key;
            void *val;
            const char *name;
            const svn_wc_entry_t *entry;
            const char *down_path;

            apr_hash_this (hi, &key, NULL, &val);
            name = key;
            entry = val;

⌨️ 快捷键说明

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