📄 add.c
字号:
/* Recurse on directories; add files; ignore the rest. */
if (this_entry.filetype == APR_DIR)
{
SVN_ERR (add_dir_recursive (fullpath, dir_access, force,
ctx, subpool));
}
else if (this_entry.filetype != APR_UNKFILE)
{
err = add_file (fullpath, ctx, dir_access, subpool);
if (err && err->apr_err == SVN_ERR_ENTRY_EXISTS && force)
svn_error_clear (err);
else if (err)
return err;
}
/* Clean out the per-iteration pool. */
svn_pool_clear (subpool);
}
/* Check that the loop exited cleanly. */
if (! (APR_STATUS_IS_ENOENT (err->apr_err)))
{
return svn_error_createf
(err->apr_err, err,
_("Error during recursive add of '%s'"), dirname);
}
else /* Yes, it exited cleanly, so close the dir. */
{
apr_status_t apr_err;
svn_error_clear (err);
apr_err = apr_dir_close (dir);
if (apr_err)
return svn_error_wrap_apr
(apr_err, _("Can't close directory '%s'"), dirname);
}
/* Opened by svn_wc_add */
SVN_ERR (svn_wc_adm_close (dir_access));
/* Destroy the per-iteration pool. */
svn_pool_destroy (subpool);
return SVN_NO_ERROR;
}
/* The main logic of the public svn_client_add; the only difference
is that this function uses an existing access baton.
(svn_client_add just generates an access baton and calls this func.) */
static svn_error_t *
add (const char *path,
svn_boolean_t recursive,
svn_boolean_t force,
svn_wc_adm_access_t *adm_access,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
svn_node_kind_t kind;
svn_error_t *err;
SVN_ERR (svn_io_check_path (path, &kind, pool));
if ((kind == svn_node_dir) && recursive)
err = add_dir_recursive (path, adm_access, force, ctx, pool);
else if (kind == svn_node_file)
err = add_file (path, ctx, adm_access, pool);
else
err = svn_wc_add (path, adm_access, NULL, SVN_INVALID_REVNUM,
ctx->cancel_func, ctx->cancel_baton,
ctx->notify_func, ctx->notify_baton, pool);
/* Ignore SVN_ERR_ENTRY_EXISTS when FORCE is set. */
if (err && err->apr_err == SVN_ERR_ENTRY_EXISTS && force)
{
svn_error_clear (err);
err = SVN_NO_ERROR;
}
return err;
}
svn_error_t *
svn_client_add (const char *path,
svn_boolean_t recursive,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
svn_error_t *err, *err2;
svn_wc_adm_access_t *adm_access;
const char *parent_path = svn_path_dirname (path, pool);
SVN_ERR (svn_wc_adm_open2 (&adm_access, NULL, parent_path,
TRUE, 0, pool));
err = add (path, recursive, FALSE, adm_access, ctx, pool);
err2 = svn_wc_adm_close (adm_access);
if (err2)
{
if (err)
svn_error_clear (err2);
else
err = err2;
}
return err;
}
svn_error_t *
svn_client_add2 (const char *path,
svn_boolean_t recursive,
svn_boolean_t force,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
svn_error_t *err, *err2;
svn_wc_adm_access_t *adm_access;
const char *parent_path = svn_path_dirname (path, pool);
SVN_ERR (svn_wc_adm_open2 (&adm_access, NULL, parent_path,
TRUE, 0, pool));
err = add (path, recursive, force, adm_access, ctx, pool);
err2 = svn_wc_adm_close (adm_access);
if (err2)
{
if (err)
svn_error_clear (err2);
else
err = err2;
}
return err;
}
static svn_error_t *
path_driver_cb_func (void **dir_baton,
void *parent_baton,
void *callback_baton,
const char *path,
apr_pool_t *pool)
{
const svn_delta_editor_t *editor = callback_baton;
return editor->add_directory (path, parent_baton, NULL,
SVN_INVALID_REVNUM, pool, dir_baton);
}
static svn_error_t *
mkdir_urls (svn_client_commit_info_t **commit_info,
const apr_array_header_t *paths,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
void *ra_baton, *session;
svn_ra_plugin_t *ra_lib;
const svn_delta_editor_t *editor;
void *edit_baton;
void *commit_baton;
const char *log_msg;
apr_array_header_t *targets;
svn_error_t *err;
const char *common;
int i;
/* Condense our list of mkdir targets. */
SVN_ERR (svn_path_condense_targets (&common, &targets, paths, FALSE, pool));
if (! targets->nelts)
{
const char *bname;
svn_path_split (common, &common, &bname, pool);
APR_ARRAY_PUSH (targets, const char *) = bname;
}
else
{
svn_boolean_t resplit = FALSE;
/* We can't "mkdir" the root of an editor drive, so if one of
our targets is the empty string, we need to back everything
up by a path component. */
for (i = 0; i < targets->nelts; i++)
{
const char *path = APR_ARRAY_IDX (targets, i, const char *);
if (! *path)
{
resplit = TRUE;
break;
}
}
if (resplit)
{
const char *bname;
svn_path_split (common, &common, &bname, pool);
for (i = 0; i < targets->nelts; i++)
{
const char *path = APR_ARRAY_IDX (targets, i, const char *);
path = svn_path_join (bname, path, pool);
APR_ARRAY_IDX (targets, i, const char *) = path;
}
}
}
/* Create new commit items and add them 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, targets->nelts, sizeof (item));
for (i = 0; i < targets->nelts; i++)
{
const char *path = APR_ARRAY_IDX (targets, i, const char *);
item = apr_pcalloc (pool, sizeof (*item));
item->url = svn_path_join (common, path, pool);
item->state_flags = SVN_CLIENT_COMMIT_ITEM_ADD;
APR_ARRAY_PUSH (commit_items, svn_client_commit_item_t *) = item;
}
SVN_ERR ((*ctx->log_msg_func) (&log_msg, &tmp_file, commit_items,
ctx->log_msg_baton, pool));
if (! log_msg)
return SVN_NO_ERROR;
}
else
log_msg = "";
/* 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, common, pool));
/* Open an RA session for the URL. Note that we don't have a local
directory, nor a place to put temp files. */
SVN_ERR (svn_client__open_ra_session (&session, ra_lib, common, NULL,
NULL, NULL, FALSE, TRUE,
ctx, pool));
/* URI-decode each target. */
for (i = 0; i < targets->nelts; i++)
{
const char *path = APR_ARRAY_IDX (targets, i, const char *);
path = svn_path_uri_decode (path, pool);
APR_ARRAY_IDX (targets, i, const char *) = path;
}
/* Fetch RA commit editor */
SVN_ERR (svn_client__commit_get_baton (&commit_baton, commit_info, pool));
SVN_ERR (ra_lib->get_commit_editor (session, &editor, &edit_baton,
log_msg, svn_client__commit_callback,
commit_baton, pool));
/* Call the path-based editor driver. */
err = svn_delta_path_driver (editor, edit_baton, SVN_INVALID_REVNUM,
targets, path_driver_cb_func,
(void *)editor, 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;
}
svn_error_t *
svn_client_mkdir (svn_client_commit_info_t **commit_info,
const apr_array_header_t *paths,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
if (! paths->nelts)
return SVN_NO_ERROR;
if (svn_path_is_url (APR_ARRAY_IDX (paths, 0, const char *)))
{
SVN_ERR (mkdir_urls (commit_info, paths, ctx, pool));
}
else
{
/* This is a regular "mkdir" + "svn add" */
apr_pool_t *subpool = svn_pool_create (pool);
svn_error_t *err;
int i;
for (i = 0; i < paths->nelts; i++)
{
const char *path = APR_ARRAY_IDX (paths, i, const char *);
/* See if the user wants us to stop. */
if (ctx->cancel_func)
SVN_ERR (ctx->cancel_func (ctx->cancel_baton));
SVN_ERR (svn_io_dir_make (path, APR_OS_DEFAULT, pool));
err = svn_client_add (path, FALSE, ctx, pool);
/* Trying to add a directory with the same name as a file that is
scheduled for deletion is not supported. Leaving an unversioned
directory makes the working copy hard to use. */
if (err && err->apr_err == SVN_ERR_WC_NODE_KIND_CHANGE)
{
svn_error_t *err2 = svn_io_remove_dir (path, pool);
if (err2)
svn_error_clear (err2);
}
SVN_ERR (err);
svn_pool_clear (subpool);
}
svn_pool_destroy (subpool);
}
return SVN_NO_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -