Alien-SVN
view release on metacpan or search on metacpan
src/subversion/subversion/libsvn_client/commit_util.c view on Meta::CPAN
const char *local_abspath,
const svn_wc_status3_t *status,
apr_pool_t *scratch_pool);
static svn_error_t *
harvest_committables(const char *local_abspath,
svn_client__committables_t *committables,
apr_hash_t *lock_tokens,
const char *copy_mode_relpath,
svn_depth_t depth,
svn_boolean_t just_locked,
apr_hash_t *changelists,
apr_hash_t *danglers,
svn_client__check_url_kind_t check_url_func,
void *check_url_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
svn_wc_context_t *wc_ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
struct harvest_baton baton;
SVN_ERR_ASSERT((just_locked && lock_tokens) || !just_locked);
baton.root_abspath = local_abspath;
baton.committables = committables;
baton.lock_tokens = lock_tokens;
baton.commit_relpath = copy_mode_relpath;
baton.depth = depth;
baton.just_locked = just_locked;
baton.changelists = changelists;
baton.danglers = danglers;
baton.check_url_func = check_url_func;
baton.check_url_baton = check_url_baton;
baton.notify_func = notify_func;
baton.notify_baton = notify_baton;
baton.wc_ctx = wc_ctx;
baton.result_pool = result_pool;
baton.skip_below_abspath = NULL;
SVN_ERR(svn_wc_walk_status(wc_ctx,
local_abspath,
depth,
(copy_mode_relpath != NULL) /* get_all */,
FALSE /* no_ignore */,
FALSE /* ignore_text_mods */,
NULL /* ignore_patterns */,
harvest_status_callback,
&baton,
cancel_func, cancel_baton,
scratch_pool));
return SVN_NO_ERROR;
}
static svn_error_t *
harvest_not_present_for_copy(svn_wc_context_t *wc_ctx,
const char *local_abspath,
svn_client__committables_t *committables,
const char *repos_root_url,
const char *commit_relpath,
svn_client__check_url_kind_t check_url_func,
void *check_url_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
const apr_array_header_t *children;
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
int i;
/* A function to retrieve not present children would be nice to have */
SVN_ERR(svn_wc__node_get_children_of_working_node(
&children, wc_ctx, local_abspath, TRUE,
scratch_pool, iterpool));
for (i = 0; i < children->nelts; i++)
{
const char *this_abspath = APR_ARRAY_IDX(children, i, const char *);
const char *name = svn_dirent_basename(this_abspath, NULL);
const char *this_commit_relpath;
svn_boolean_t not_present;
svn_node_kind_t kind;
svn_pool_clear(iterpool);
SVN_ERR(svn_wc__node_is_not_present(¬_present, NULL, NULL, wc_ctx,
this_abspath, FALSE, scratch_pool));
if (!not_present)
continue;
if (commit_relpath == NULL)
this_commit_relpath = NULL;
else
this_commit_relpath = svn_relpath_join(commit_relpath, name,
iterpool);
/* We should check if we should really add a delete operation */
if (check_url_func)
{
svn_revnum_t parent_rev;
const char *parent_repos_relpath;
const char *parent_repos_root_url;
const char *node_url;
/* Determine from what parent we would be the deleted child */
SVN_ERR(svn_wc__node_get_origin(
NULL, &parent_rev, &parent_repos_relpath,
&parent_repos_root_url, NULL, NULL,
wc_ctx,
svn_dirent_dirname(this_abspath,
scratch_pool),
FALSE, scratch_pool, scratch_pool));
node_url = svn_path_url_add_component2(
svn_path_url_add_component2(parent_repos_root_url,
parent_repos_relpath,
scratch_pool),
svn_dirent_basename(this_abspath, NULL),
iterpool);
SVN_ERR(check_url_func(check_url_baton, &kind,
node_url, parent_rev, iterpool));
if (kind == svn_node_none)
continue; /* This node can't be deleted */
}
else
SVN_ERR(svn_wc_read_kind2(&kind, wc_ctx, this_abspath,
TRUE, TRUE, scratch_pool));
SVN_ERR(add_committable(committables, this_abspath, kind,
repos_root_url,
this_commit_relpath,
SVN_INVALID_REVNUM,
NULL /* copyfrom_relpath */,
SVN_INVALID_REVNUM /* copyfrom_rev */,
NULL /* moved_from_abspath */,
SVN_CLIENT_COMMIT_ITEM_DELETE,
NULL, NULL,
result_pool, scratch_pool));
}
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
/* Implements svn_wc_status_func4_t */
static svn_error_t *
src/subversion/subversion/libsvn_client/commit_util.c view on Meta::CPAN
*/
if (matches_changelists
&& (is_harvest_root || baton->changelists)
&& state_flags
&& (is_added || (is_deleted && is_op_root && status->copied))
&& baton->danglers)
{
/* If a node is added, its parent must exist in the repository at the
time of committing */
apr_hash_t *danglers = baton->danglers;
svn_boolean_t parent_added;
const char *parent_abspath = svn_dirent_dirname(local_abspath,
scratch_pool);
/* First check if parent is already in the list of commits
(Common case for GUI clients that provide a list of commit targets) */
if (look_up_committable(committables, parent_abspath, scratch_pool))
parent_added = FALSE; /* Skip all expensive checks */
else
SVN_ERR(svn_wc__node_is_added(&parent_added, wc_ctx, parent_abspath,
scratch_pool));
if (parent_added)
{
const char *copy_root_abspath;
svn_boolean_t parent_is_copy;
/* The parent is added, so either it is a copy, or a locally added
* directory. In either case, we require the op-root of the parent
* to be part of the commit. See issue #4059. */
SVN_ERR(svn_wc__node_get_origin(&parent_is_copy, NULL, NULL, NULL,
NULL, ©_root_abspath,
wc_ctx, parent_abspath,
FALSE, scratch_pool, scratch_pool));
if (parent_is_copy)
parent_abspath = copy_root_abspath;
if (!svn_hash_gets(danglers, parent_abspath))
{
svn_hash_sets(danglers, apr_pstrdup(result_pool, parent_abspath),
apr_pstrdup(result_pool, local_abspath));
}
}
}
if (is_deleted && !is_added)
{
/* Skip all descendants */
if (status->kind == svn_node_dir)
baton->skip_below_abspath = apr_pstrdup(baton->result_pool,
local_abspath);
return SVN_NO_ERROR;
}
/* Recursively handle each node according to depth, except when the
node is only being deleted, or is in an added tree (as added trees
use the normal commit handling). */
if (copy_mode && !is_added && !is_deleted && status->kind == svn_node_dir)
{
SVN_ERR(harvest_not_present_for_copy(wc_ctx, local_abspath, committables,
repos_root_url, commit_relpath,
baton->check_url_func,
baton->check_url_baton,
result_pool, scratch_pool));
}
return SVN_NO_ERROR;
}
/* Baton for handle_descendants */
struct handle_descendants_baton
{
svn_wc_context_t *wc_ctx;
svn_cancel_func_t cancel_func;
void *cancel_baton;
svn_client__check_url_kind_t check_url_func;
void *check_url_baton;
svn_client__committables_t *committables;
};
/* Helper for the commit harvesters */
static svn_error_t *
handle_descendants(void *baton,
const void *key, apr_ssize_t klen, void *val,
apr_pool_t *pool)
{
struct handle_descendants_baton *hdb = baton;
apr_array_header_t *commit_items = val;
apr_pool_t *iterpool = svn_pool_create(pool);
const char *repos_root_url = key;
int i;
for (i = 0; i < commit_items->nelts; i++)
{
svn_client_commit_item3_t *item =
APR_ARRAY_IDX(commit_items, i, svn_client_commit_item3_t *);
const apr_array_header_t *absent_descendants;
int j;
/* Is this a copy operation? */
if (!(item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD)
|| ! item->copyfrom_url)
continue;
if (hdb->cancel_func)
SVN_ERR(hdb->cancel_func(hdb->cancel_baton));
svn_pool_clear(iterpool);
SVN_ERR(svn_wc__get_not_present_descendants(&absent_descendants,
hdb->wc_ctx, item->path,
iterpool, iterpool));
for (j = 0; j < absent_descendants->nelts; j++)
{
svn_node_kind_t kind;
svn_client_commit_item3_t *desc_item;
const char *relpath = APR_ARRAY_IDX(absent_descendants, j,
const char *);
const char *local_abspath = svn_dirent_join(item->path, relpath,
iterpool);
/* ### Need a sub-iterpool? */
/* We found a 'not present' descendant during a copy (at op_depth>0),
this is most commonly caused by copying some mixed revision tree.
In this case not present can imply that the node does not exist
in the parent revision, or that the node does. But we want to copy
the working copy state in which it does not exist, but might be
replaced. */
desc_item = svn_hash_gets(hdb->committables->by_path, local_abspath);
/* If the path has a commit operation (possibly at an higher
op_depth, we might want to turn an add in a replace. */
if (desc_item)
{
const char *dir;
svn_boolean_t found_intermediate = FALSE;
if (desc_item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
continue; /* We already have a delete or replace */
else if (!(desc_item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD))
continue; /* Not a copy/add, just a modification */
dir = svn_dirent_dirname(local_abspath, iterpool);
while (strcmp(dir, item->path))
{
svn_client_commit_item3_t *i_item;
i_item = svn_hash_gets(hdb->committables->by_path, dir);
if (i_item)
{
if ((i_item->state_flags & SVN_CLIENT_COMMIT_ITEM_DELETE)
|| (i_item->state_flags & SVN_CLIENT_COMMIT_ITEM_ADD))
{
found_intermediate = TRUE;
break;
}
}
dir = svn_dirent_dirname(dir, iterpool);
}
if (found_intermediate)
continue; /* Some intermediate ancestor is an add or delete */
( run in 1.169 second using v1.01-cache-2.11-cpan-524268b4103 )