aboutsummaryrefslogtreecommitdiffstats
path: root/subversion/libsvn_client/commit.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_client/commit.c')
-rw-r--r--subversion/libsvn_client/commit.c185
1 files changed, 140 insertions, 45 deletions
diff --git a/subversion/libsvn_client/commit.c b/subversion/libsvn_client/commit.c
index 4a945c887aa9..df2f5f7c5224 100644
--- a/subversion/libsvn_client/commit.c
+++ b/subversion/libsvn_client/commit.c
@@ -500,6 +500,129 @@ append_externals_as_explicit_targets(apr_array_header_t *rel_targets,
return SVN_NO_ERROR;
}
+/* Crawl the working copy for commit items.
+ */
+static svn_error_t *
+harvest_committables(apr_array_header_t **commit_items_p,
+ apr_hash_t **committables_by_path_p,
+ apr_hash_t **lock_tokens,
+ const char *base_dir_abspath,
+ const apr_array_header_t *targets,
+ int depth_empty_start,
+ svn_depth_t depth,
+ svn_boolean_t just_locked,
+ const apr_array_header_t *changelists,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct check_url_kind_baton cukb;
+ svn_client__committables_t *committables;
+ apr_hash_index_t *hi;
+
+ /* Prepare for when we have a copy containing not-present nodes. */
+ cukb.pool = scratch_pool;
+ cukb.session = NULL; /* ### Can we somehow reuse session? */
+ cukb.repos_root_url = NULL;
+ cukb.ctx = ctx;
+
+ SVN_ERR(svn_client__harvest_committables(&committables, lock_tokens,
+ base_dir_abspath, targets,
+ depth_empty_start, depth,
+ just_locked,
+ changelists,
+ check_url_kind, &cukb,
+ ctx, result_pool, scratch_pool));
+ if (apr_hash_count(committables->by_repository) == 0)
+ {
+ *commit_items_p = NULL;
+ return SVN_NO_ERROR; /* Nothing to do */
+ }
+ else if (apr_hash_count(committables->by_repository) > 1)
+ {
+ return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+ _("Commit can only commit to a single repository at a time.\n"
+ "Are all targets part of the same working copy?"));
+ }
+
+ hi = apr_hash_first(scratch_pool, committables->by_repository);
+ *commit_items_p = apr_hash_this_val(hi);
+ if (committables_by_path_p)
+ *committables_by_path_p = committables->by_path;
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client__wc_replay(const char *src_wc_abspath,
+ const apr_array_header_t *targets,
+ svn_depth_t depth,
+ const apr_array_header_t *changelists,
+ const svn_delta_editor_t *editor,
+ void *edit_baton,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
+{
+ const char *base_abspath;
+ apr_array_header_t *rel_targets;
+ apr_hash_t *lock_tokens;
+ apr_array_header_t *commit_items;
+ svn_client__pathrev_t *base;
+ const char *base_url;
+ svn_wc_notify_func2_t saved_notify_func;
+ void *saved_notify_baton;
+
+ /* Condense the target list. This makes all targets absolute. */
+ SVN_ERR(svn_dirent_condense_targets(&base_abspath, &rel_targets, targets,
+ FALSE, pool, pool));
+
+ /* No targets means nothing to commit, so just return. */
+ if (base_abspath == NULL)
+ return SVN_NO_ERROR;
+
+ SVN_ERR_ASSERT(rel_targets != NULL);
+
+ /* If we calculated only a base and no relative targets, this
+ must mean that we are being asked to commit (effectively) a
+ single path. */
+ if (rel_targets->nelts == 0)
+ APR_ARRAY_PUSH(rel_targets, const char *) = "";
+
+ /* Crawl the working copy for commit items. */
+ SVN_ERR(harvest_committables(&commit_items, NULL /*committables_by_path_p*/,
+ &lock_tokens,
+ base_abspath, rel_targets,
+ -1 /*depth_empty_start*/,
+ depth,
+ FALSE /*just_locked*/,
+ changelists,
+ ctx, pool, pool));
+ if (!commit_items)
+ {
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(svn_client__wc_node_get_base(&base,
+ src_wc_abspath, ctx->wc_ctx, pool, pool));
+ base_url = base->url;
+ /* Sort our COMMIT_ITEMS by URL and find their relative URL-paths. */
+ SVN_ERR(svn_client__condense_commit_items2(base_url, commit_items, pool));
+
+ saved_notify_func = ctx->notify_func2;
+ saved_notify_baton = ctx->notify_baton2;
+ ctx->notify_func2 = notify_func;
+ ctx->notify_baton2 = notify_baton;
+ /* BASE_URL is only used here in notifications & errors */
+ SVN_ERR(svn_client__do_commit(base_url, commit_items,
+ editor, edit_baton,
+ NULL /*notify_prefix*/, NULL /*sha1_checksums*/,
+ ctx, pool, pool));
+ ctx->notify_func2 = saved_notify_func;
+ ctx->notify_baton2 = saved_notify_baton;
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_client_commit6(const apr_array_header_t *targets,
svn_depth_t depth,
@@ -525,7 +648,7 @@ svn_client_commit6(const apr_array_header_t *targets,
apr_array_header_t *rel_targets;
apr_array_header_t *lock_targets;
apr_array_header_t *locks_obtained;
- svn_client__committables_t *committables;
+ apr_hash_t *committables_by_path;
apr_hash_t *lock_tokens;
apr_hash_t *sha1_checksums;
apr_array_header_t *commit_items;
@@ -615,55 +738,27 @@ svn_client_commit6(const apr_array_header_t *targets,
pool);
/* Crawl the working copy for commit items. */
- {
- struct check_url_kind_baton cukb;
-
- /* Prepare for when we have a copy containing not-present nodes. */
- cukb.pool = iterpool;
- cukb.session = NULL; /* ### Can we somehow reuse session? */
- cukb.repos_root_url = NULL;
- cukb.ctx = ctx;
-
- cmt_err = svn_error_trace(
- svn_client__harvest_committables(&committables,
- &lock_tokens,
- base_abspath,
- rel_targets,
- depth_empty_after,
- depth,
- ! keep_locks,
- changelists,
- check_url_kind,
- &cukb,
- ctx,
- pool,
- iterpool));
-
- svn_pool_clear(iterpool);
- }
+ cmt_err = svn_error_trace(
+ harvest_committables(&commit_items, &committables_by_path,
+ &lock_tokens,
+ base_abspath,
+ rel_targets,
+ depth_empty_after,
+ depth,
+ ! keep_locks,
+ changelists,
+ ctx,
+ pool,
+ iterpool));
+ svn_pool_clear(iterpool);
if (cmt_err)
goto cleanup;
- if (apr_hash_count(committables->by_repository) == 0)
+ if (!commit_items)
{
goto cleanup; /* Nothing to do */
}
- else if (apr_hash_count(committables->by_repository) > 1)
- {
- cmt_err = svn_error_create(
- SVN_ERR_UNSUPPORTED_FEATURE, NULL,
- _("Commit can only commit to a single repository at a time.\n"
- "Are all targets part of the same working copy?"));
- goto cleanup;
- }
-
- {
- apr_hash_index_t *hi = apr_hash_first(iterpool,
- committables->by_repository);
-
- commit_items = apr_hash_this_val(hi);
- }
/* If our array of targets contains only locks (and no actual file
or prop modifications), then we return here to avoid committing a
@@ -713,7 +808,7 @@ svn_client_commit6(const apr_array_header_t *targets,
if (moved_from_abspath && delete_op_root_abspath)
{
svn_client_commit_item3_t *delete_half =
- svn_hash_gets(committables->by_path, delete_op_root_abspath);
+ svn_hash_gets(committables_by_path, delete_op_root_abspath);
if (!delete_half)
{
@@ -769,7 +864,7 @@ svn_client_commit6(const apr_array_header_t *targets,
if (moved_to_abspath && copy_op_root_abspath &&
strcmp(moved_to_abspath, copy_op_root_abspath) == 0 &&
- svn_hash_gets(committables->by_path, copy_op_root_abspath)
+ svn_hash_gets(committables_by_path, copy_op_root_abspath)
== NULL)
{
cmt_err = svn_error_createf(