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

📄 copy.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
  /* Figure out the basename that will result from this operation. */
  SVN_ERR (ra_lib->check_path (sess, dst_rel, youngest, &dst_kind, pool));
  if (dst_kind == svn_node_none)
    {
      /* do nothing */
    }
  else if (dst_kind == svn_node_file)
    {
      /* We disallow the overwriting of files. */
      return svn_error_createf (SVN_ERR_FS_ALREADY_EXISTS, NULL,
                                _("Path '%s' already exists"), dst_rel);
    }
  else if (dst_kind == svn_node_dir)
    {
      /* As a matter of client-side policy, we prevent overwriting any
         pre-existing directory.  So we append src_url's basename to
         dst_rel, and see if that already exists.  */
      svn_node_kind_t attempt_kind;
      const char *bname;

      bname = svn_path_uri_decode (svn_path_basename (src_url, pool), pool);
      dst_rel = svn_path_join (dst_rel, bname, pool);
      SVN_ERR (ra_lib->check_path (sess, dst_rel, youngest,
                                   &attempt_kind, pool));
      if (attempt_kind != svn_node_none)
        return svn_error_createf (SVN_ERR_FS_ALREADY_EXISTS, NULL,
                                  _("Path '%s' already exists"), dst_rel);
    }
  else
    {
      return svn_error_createf (SVN_ERR_NODE_UNKNOWN_KIND, NULL,
                                _("Unrecognized node kind of '%s'"), dst_url);
    }

  /* Create a new commit item and add it to the array. */
  if (ctx->log_msg_func)
    {
      svn_client_commit_item_t *item;
      const char *tmp_file;
      apr_array_header_t *commit_items 
        = apr_array_make (pool, 2, sizeof (item));
      
      item = apr_pcalloc (pool, sizeof (*item));
      item->url = svn_path_join (top_url, dst_rel, pool);
      item->state_flags = SVN_CLIENT_COMMIT_ITEM_ADD;
      (*((svn_client_commit_item_t **) apr_array_push (commit_items))) = item;
      if (is_move && (! resurrection))
        {
          item = apr_pcalloc (pool, sizeof (*item));
          item->url = svn_path_join (top_url, src_rel, pool);
          item->state_flags = SVN_CLIENT_COMMIT_ITEM_DELETE;
          (*((svn_client_commit_item_t **) apr_array_push (commit_items))) = 
            item;
        }
      SVN_ERR ((*ctx->log_msg_func) (&message, &tmp_file, commit_items, 
                                     ctx->log_msg_baton, pool));
      if (! message)
        return SVN_NO_ERROR;
    }
  else
    message = "";


  /* Fetch RA commit editor. */
  SVN_ERR (svn_client__commit_get_baton (&commit_baton, commit_info, pool));
  SVN_ERR (ra_lib->get_commit_editor (sess, &editor, &edit_baton, message,
                                      svn_client__commit_callback,
                                      commit_baton, pool));

  /* Setup our PATHS for the path-based editor drive. */
  APR_ARRAY_PUSH (paths, const char *) = dst_rel;
  if (is_move && (! resurrection))
    APR_ARRAY_PUSH (paths, const char *) = src_rel;

  /* Setup the callback baton. */
  cb_baton.editor = editor;
  cb_baton.edit_baton = edit_baton;
  cb_baton.src_kind = src_kind;
  cb_baton.src_url = src_url;
  cb_baton.src_path = src_rel;
  cb_baton.dst_path = dst_rel;
  cb_baton.is_move = is_move;
  cb_baton.src_revnum = src_revnum;
  cb_baton.resurrection = resurrection;

  /* Call the path-based editor driver. */
  err = svn_delta_path_driver (editor, edit_baton, youngest, paths,
                               path_driver_cb_func, &cb_baton, pool);
  if (err)
    {
      /* At least try to abort the edit (and fs txn) before throwing err. */
      svn_error_clear (editor->abort_edit (edit_baton, pool));
      return err;
    }

  /* Close the edit. */
  SVN_ERR (editor->close_edit (edit_baton, pool));

  return SVN_NO_ERROR;
}



static svn_error_t *
remove_tmpfiles (apr_hash_t *tempfiles,
                 svn_cancel_func_t cancel_func,
                 void *cancel_baton,
                 apr_pool_t *pool)
{
  apr_hash_index_t *hi;

  /* Split if there's nothing to be done. */
  if (! tempfiles)
    return SVN_NO_ERROR;

  /* Clean up any tempfiles. */
  for (hi = apr_hash_first (pool, tempfiles); hi; hi = apr_hash_next (hi))
    {
      const void *key;
      apr_ssize_t keylen;
      void *val;
      svn_node_kind_t kind;

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

      apr_hash_this (hi, &key, &keylen, &val);
      SVN_ERR (svn_io_check_path ((const char *)key, &kind, pool));
      if (kind == svn_node_file)
        SVN_ERR (svn_io_remove_file ((const char *)key, pool));
    }

  return SVN_NO_ERROR;
}



static svn_error_t *
reconcile_errors (svn_error_t *commit_err,
                  svn_error_t *unlock_err,
                  svn_error_t *cleanup_err,
                  apr_pool_t *pool)
{
  svn_error_t *err;

  /* Early release (for good behavior). */
  if (! (commit_err || unlock_err || cleanup_err))
    return SVN_NO_ERROR;

  /* If there was a commit error, start off our error chain with
     that. */
  if (commit_err)
    {
      commit_err = svn_error_quick_wrap 
        (commit_err, _("Commit failed (details follow):"));
      err = commit_err;
    }

  /* Else, create a new "general" error that will lead off the errors
     that follow. */
  else
    err = svn_error_create (SVN_ERR_BASE, NULL,
                            _("Commit succeeded, but other errors follow:"));

  /* If there was an unlock error... */
  if (unlock_err)
    {
      /* Wrap the error with some headers. */
      unlock_err = svn_error_quick_wrap 
        (unlock_err, _("Error unlocking locked dirs (details follow):"));

      /* Append this error to the chain. */
      svn_error_compose (err, unlock_err);
    }

  /* If there was a cleanup error... */
  if (cleanup_err)
    {
      /* Wrap the error with some headers. */
      cleanup_err = svn_error_quick_wrap 
        (cleanup_err, _("Error in post-commit clean-up (details follow):"));

      /* Append this error to the chain. */
      svn_error_compose (err, cleanup_err);
    }

  return err;
}



static svn_error_t *
wc_to_repos_copy (svn_client_commit_info_t **commit_info,
                  const char *src_path, 
                  const char *dst_url, 
                  svn_client_ctx_t *ctx,
                  apr_pool_t *pool)
{
  const char *anchor, *target, *base_name, *message;
  void *ra_baton, *session;
  svn_ra_plugin_t *ra_lib;
  const svn_delta_editor_t *editor;
  void *edit_baton;
  svn_node_kind_t src_kind, dst_kind;
  void *commit_baton;
  apr_hash_t *committables, *tempfiles = NULL;
  svn_wc_adm_access_t *adm_access, *dir_access;
  apr_array_header_t *commit_items;
  svn_error_t *cmt_err = SVN_NO_ERROR;
  svn_error_t *unlock_err = SVN_NO_ERROR;
  svn_error_t *cleanup_err = SVN_NO_ERROR;
  svn_boolean_t commit_in_progress = FALSE;
  const char *base_path;
  const char *base_url;

  /* The commit process uses absolute paths, so we need to open the access
     baton using absolute paths, and so we really need to use absolute
     paths everywhere. */
  SVN_ERR (svn_path_get_absolute (&base_path, src_path, pool));

  SVN_ERR (svn_wc_adm_probe_open2 (&adm_access, NULL, base_path,
                                   FALSE, -1, pool));

  /* Split the DST_URL into an anchor and target. */
  svn_path_split (dst_url, &anchor, &target, pool);

  /* Get the RA vtable that matches URL. */
  SVN_ERR (svn_ra_init_ra_libs (&ra_baton, pool));
  SVN_ERR (svn_ra_get_ra_library (&ra_lib, ra_baton, anchor, pool));

  /* Open an RA session for the anchor URL. */
  SVN_ERR (svn_client__open_ra_session (&session, ra_lib, anchor,
                                        svn_wc_adm_access_path (adm_access),
                                        adm_access, NULL, TRUE, TRUE, 
                                        ctx, pool));

  /* Figure out the basename that will result from this operation. */
  SVN_ERR (ra_lib->check_path (session, svn_path_uri_decode (target, pool),
                               SVN_INVALID_REVNUM, &dst_kind, pool));
  
  /* BASE_URL defaults to DST_URL. */
  base_url = apr_pstrdup (pool, dst_url);
  if (dst_kind == svn_node_none)
    {
      /* DST_URL doesn't exist under its parent URL, so the URL we
         will be creating is DST_URL. */
    }
  else if (dst_kind == svn_node_dir)
    {
      /* DST_URL is an existing directory URL.  The URL we will be
         creating, then, is DST_URL+BASENAME. */
      svn_path_split (base_path, NULL, &base_name, pool);
      base_url = svn_path_url_add_component (base_url, base_name, pool);
    }
  else
    {
      /* DST_URL is an existing file, which can't be overwritten or
         used as a container, so error out. */
      return svn_error_createf (SVN_ERR_FS_ALREADY_EXISTS, NULL,
                                _("File '%s' already exists"), dst_url);
    }

  /* Create a new commit item and add it to the array. */
  if (ctx->log_msg_func)
    {
      svn_client_commit_item_t *item;
      const char *tmp_file;

      commit_items = apr_array_make (pool, 1, sizeof (item));      
      item = apr_pcalloc (pool, sizeof (*item));
      item->url = base_url;
      item->state_flags = SVN_CLIENT_COMMIT_ITEM_ADD;
      (*((svn_client_commit_item_t **) apr_array_push (commit_items))) = item;
      
      SVN_ERR ((*ctx->log_msg_func) (&message, &tmp_file, commit_items, 
                                     ctx->log_msg_baton, pool));
      if (! message)
        return SVN_NO_ERROR;
    }
  else
    message = "";

  /* Crawl the working copy for commit items. */
  SVN_ERR (svn_io_check_path (base_path, &src_kind, pool));
  if (src_kind == svn_node_dir)
     SVN_ERR (svn_wc_adm_retrieve (&dir_access, adm_access, base_path, pool));
  else
    dir_access = adm_access;
  if ((cmt_err = svn_client__get_copy_committables (&committables, 
                                                    base_url,
                                                    base_path,
                                                    dir_access,
                                                    ctx,
                                                    pool)))
    goto cleanup;

  /* ### todo: There should be only one hash entry, which currently
     has a hacked name until we have the entries files storing
     canonical repository URLs.  Then, the hacked name can go away and
     be replaced with a entry->repos (or whereever the entry's
     canonical repos URL is stored). */
  if (! ((commit_items = apr_hash_get (committables, 
                                       SVN_CLIENT__SINGLE_REPOS_NAME, 
                                       APR_HASH_KEY_STRING))))
    goto cleanup;

  /* Sort and condense our COMMIT_ITEMS. */
  if ((cmt_err = svn_client__condense_commit_items (&base_url, 
                                                    commit_items, 
                                                    pool)))
    goto cleanup;

  /* Open an RA session to BASE_URL. */
  if ((cmt_err = svn_client__open_ra_session (&session, ra_lib, base_url,
                                              NULL, NULL, commit_items,
                                              FALSE, FALSE,
                                              ctx, pool)))
    goto cleanup;

  /* Fetch RA commit editor. */
  SVN_ERR (svn_client__commit_get_baton (&commit_baton, commit_info, pool));
  if ((cmt_err = ra_lib->get_commit_editor (session, &editor, &edit_baton, 
                                            message,
                                            svn_client__commit_callback,
                                            commit_baton, pool)))
    goto cleanup;

  /* Make a note that we have a commit-in-progress. */
  commit_in_progress = TRUE;

  /* Perform the commit. */
  cmt_err = svn_client__do_commit (base_url, commit_items, adm_access,
                                   editor, edit_baton, 
                                   0, /* ### any notify_path_offset needed? */
                                   &tempfiles, ctx, pool);

  commit_in_progress = FALSE;

  /* Sleep to ensure timestamp integrity. */
  svn_sleep_for_timestamps ();

 cleanup:
  /* Abort the commit if it is still in progress. */
  if (commit_in_progress)
    svn_error_clear (editor->abort_edit (edit_baton, pool));

  /* It's only a read lock, so unlocking is harmless. */
  unlock_err = svn_wc_adm_close (adm_access);

  /* Remove any outstanding temporary text-base files. */
  if (tempfiles)
    cleanup_err = remove_tmpfiles (tempfiles,
                                   ctx->cancel_func, ctx->cancel_baton,
                                   pool);

  return reconcile_errors (cmt_err, unlock_err, cleanup_err, pool);
}


static svn_error_t *
repos_to_wc_copy (const char *src_url,
                  const svn_opt_revision_t *src_revision,
                  const char *dst_path, 
                  svn_client_ctx_t *ctx,
                  apr_pool_t *pool)
{
  void *ra_baton, *sess;
  svn_ra_plugin_t *ra_lib;
  svn_node_kind_t src_kind, dst_kind;
  svn_revnum_t src_revnum;
  svn_wc_adm_access_t *adm_access;
  const char *src_uuid = NULL, *dst_uuid = NULL;
  svn_boolean_t same_repositories;
  svn_opt_revision_t revision;

  /* Get the RA vtable that matches URL. */
  SVN_ERR (svn_ra_init_ra_libs (&ra_baton, pool));
  SVN_ERR (svn_ra_get_ra_library (&ra_lib, ra_baton, src_url, pool));

  /* Open a repository session to the given URL. We do not (yet) have a
     working copy, so we don't have a corresponding path and tempfiles
     cannot go into the admin area. */
  SVN_ERR (svn_client__open_ra_session (&sess, ra_lib, src_url, NULL,
                                        NULL, NULL, FALSE, TRUE, 
                                        ctx, pool));
      

⌨️ 快捷键说明

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