summaryrefslogtreecommitdiff
path: root/subversion/libsvn_client/ra.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_client/ra.c')
-rw-r--r--subversion/libsvn_client/ra.c127
1 files changed, 71 insertions, 56 deletions
diff --git a/subversion/libsvn_client/ra.c b/subversion/libsvn_client/ra.c
index a0d4cea..f98b4b0 100644
--- a/subversion/libsvn_client/ra.c
+++ b/subversion/libsvn_client/ra.c
@@ -42,6 +42,7 @@
#include "svn_private_config.h"
#include "private/svn_wc_private.h"
#include "private/svn_client_private.h"
+#include "private/svn_sorts_private.h"
/* This is the baton that we pass svn_ra_open3(), and is associated with
@@ -70,6 +71,8 @@ typedef struct callback_baton_t
/* A client context. */
svn_client_ctx_t *ctx;
+ /* Last progress reported by progress callback. */
+ apr_off_t last_progress;
} callback_baton_t;
@@ -287,6 +290,31 @@ get_client_string(void *baton,
return SVN_NO_ERROR;
}
+/* Implements svn_ra_progress_notify_func_t. Accumulates progress information
+ * for different RA sessions and reports total progress to caller. */
+static void
+progress_func(apr_off_t progress,
+ apr_off_t total,
+ void *baton,
+ apr_pool_t *pool)
+{
+ callback_baton_t *b = baton;
+ svn_client_ctx_t *public_ctx = b->ctx;
+ svn_client__private_ctx_t *private_ctx =
+ svn_client__get_private_ctx(public_ctx);
+
+ private_ctx->total_progress += (progress - b->last_progress);
+ b->last_progress = progress;
+
+ if (public_ctx->progress_func)
+ {
+ /* All RA implementations currently provide -1 for total. So it doesn't
+ make sense to develop some complex logic to combine total across all
+ RA sessions. */
+ public_ctx->progress_func(private_ctx->total_progress, -1,
+ public_ctx->progress_baton, pool);
+ }
+}
#define SVN_CLIENT__MAX_REDIRECT_ATTEMPTS 3 /* ### TODO: Make configurable. */
@@ -320,12 +348,15 @@ svn_client__open_ra_session_internal(svn_ra_session_t **ra_session,
cbtable->invalidate_wc_props = (write_dav_props && read_dav_props)
? invalidate_wc_props : NULL;
cbtable->auth_baton = ctx->auth_baton; /* new-style */
- cbtable->progress_func = ctx->progress_func;
- cbtable->progress_baton = ctx->progress_baton;
+ cbtable->progress_func = progress_func;
+ cbtable->progress_baton = cb;
cbtable->cancel_func = ctx->cancel_func ? cancel_callback : NULL;
cbtable->get_client_string = get_client_string;
if (base_dir_abspath)
cbtable->get_wc_contents = get_wc_contents;
+ cbtable->check_tunnel_func = ctx->check_tunnel_func;
+ cbtable->open_tunnel_func = ctx->open_tunnel_func;
+ cbtable->tunnel_baton = ctx->tunnel_baton;
cb->commit_items = commit_items;
cb->ctx = ctx;
@@ -403,7 +434,7 @@ svn_client__open_ra_session_internal(svn_ra_session_t **ra_session,
svn_wc_create_notify_url(corrected,
svn_wc_notify_url_redirect,
scratch_pool);
- (*ctx->notify_func2)(ctx->notify_baton2, notify, scratch_pool);
+ ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool);
}
/* Our caller will want to know what our final corrected URL was. */
@@ -614,8 +645,7 @@ svn_client__repos_location_segments(apr_array_header_t **segments,
pool);
SVN_ERR(svn_error_compose_create(
err, svn_ra_reparent(ra_session, old_session_url, pool)));
- qsort((*segments)->elts, (*segments)->nelts,
- (*segments)->elt_size, compare_segments);
+ svn_sort__array(*segments, compare_segments);
return SVN_NO_ERROR;
}
@@ -627,6 +657,9 @@ svn_client__repos_location_segments(apr_array_header_t **segments,
* END_REVNUM must be valid revision numbers except that END_REVNUM may
* be SVN_INVALID_REVNUM if END_URL is NULL.
*
+ * YOUNGEST_REV is the already retrieved youngest revision of the ra session,
+ * but can be SVN_INVALID_REVNUM if the value is not already retrieved.
+ *
* RA_SESSION is an open RA session parented at URL.
*/
static svn_error_t *
@@ -637,6 +670,7 @@ repos_locations(const char **start_url,
svn_revnum_t peg_revnum,
svn_revnum_t start_revnum,
svn_revnum_t end_revnum,
+ svn_revnum_t youngest_rev,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@@ -644,9 +678,9 @@ repos_locations(const char **start_url,
apr_array_header_t *revs;
apr_hash_t *rev_locs;
- SVN_ERR_ASSERT(peg_revnum != SVN_INVALID_REVNUM);
- SVN_ERR_ASSERT(start_revnum != SVN_INVALID_REVNUM);
- SVN_ERR_ASSERT(end_revnum != SVN_INVALID_REVNUM || end_url == NULL);
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(peg_revnum));
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(start_revnum));
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(end_revnum) || end_url == NULL);
/* Avoid a network request in the common easy case. */
if (start_revnum == peg_revnum
@@ -661,6 +695,27 @@ repos_locations(const char **start_url,
SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_url, scratch_pool));
+ /* Handle another common case: The repository root can't move */
+ if (! strcmp(repos_url, url))
+ {
+ if (! SVN_IS_VALID_REVNUM(youngest_rev))
+ SVN_ERR(svn_ra_get_latest_revnum(ra_session, &youngest_rev,
+ scratch_pool));
+
+ if (start_revnum > youngest_rev
+ || (SVN_IS_VALID_REVNUM(end_revnum) && (end_revnum > youngest_rev)))
+ return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
+ _("No such revision %ld"),
+ (start_revnum > youngest_rev)
+ ? start_revnum : end_revnum);
+
+ if (start_url)
+ *start_url = apr_pstrdup(result_pool, repos_url);
+ if (end_url)
+ *end_url = apr_pstrdup(result_pool, repos_url);
+ return SVN_NO_ERROR;
+ }
+
revs = apr_array_make(scratch_pool, 2, sizeof(svn_revnum_t));
APR_ARRAY_PUSH(revs, svn_revnum_t) = start_revnum;
if (end_revnum != start_revnum && end_revnum != SVN_INVALID_REVNUM)
@@ -716,7 +771,7 @@ svn_client__repos_location(svn_client__pathrev_t **op_loc_p,
peg_loc->url, scratch_pool));
err = repos_locations(&op_url, NULL, ra_session,
peg_loc->url, peg_loc->rev,
- op_revnum, SVN_INVALID_REVNUM,
+ op_revnum, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
result_pool, scratch_pool);
SVN_ERR(svn_error_compose_create(
err, svn_ra_reparent(ra_session, old_session_url, scratch_pool)));
@@ -776,7 +831,7 @@ svn_client__repos_locations(const char **start_url,
svn_boolean_t is_copy;
SVN_ERR(svn_wc__node_get_origin(&is_copy, &peg_revnum, &repos_relpath,
- &repos_root_url, NULL, NULL,
+ &repos_root_url, NULL, NULL, NULL,
ctx->wc_ctx, local_abspath_or_url,
FALSE, subpool, subpool));
@@ -856,7 +911,7 @@ svn_client__repos_locations(const char **start_url,
SVN_ERR(repos_locations(start_url, end_url,
ra_session, url, peg_revnum,
- start_revnum, end_revnum,
+ start_revnum, end_revnum, youngest_rev,
pool, subpool));
svn_pool_destroy(subpool);
return SVN_NO_ERROR;
@@ -888,9 +943,9 @@ svn_client__calc_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
remembering the youngest matching location. */
for (hi = apr_hash_first(scratch_pool, history1); hi; hi = apr_hash_next(hi))
{
- const char *path = svn__apr_hash_index_key(hi);
- apr_ssize_t path_len = svn__apr_hash_index_klen(hi);
- svn_rangelist_t *ranges1 = svn__apr_hash_index_val(hi);
+ const char *path = apr_hash_this_key(hi);
+ apr_ssize_t path_len = apr_hash_this_key_len(hi);
+ svn_rangelist_t *ranges1 = apr_hash_this_val(hi);
svn_rangelist_t *ranges2, *common;
ranges2 = apr_hash_get(history2, path, path_len);
@@ -992,48 +1047,6 @@ svn_client__get_youngest_common_ancestor(svn_client__pathrev_t **ancestor_p,
return SVN_NO_ERROR;
}
-svn_error_t *
-svn_client__youngest_common_ancestor(const char **ancestor_url,
- svn_revnum_t *ancestor_rev,
- const char *path_or_url1,
- const svn_opt_revision_t *revision1,
- const char *path_or_url2,
- const svn_opt_revision_t *revision2,
- svn_client_ctx_t *ctx,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- apr_pool_t *sesspool = svn_pool_create(scratch_pool);
- svn_ra_session_t *session;
- svn_client__pathrev_t *loc1, *loc2, *ancestor;
-
- /* Resolve the two locations */
- SVN_ERR(svn_client__ra_session_from_path2(&session, &loc1,
- path_or_url1, NULL,
- revision1, revision1,
- ctx, sesspool));
- SVN_ERR(svn_client__resolve_rev_and_url(&loc2, session,
- path_or_url2, revision2, revision2,
- ctx, scratch_pool));
-
- SVN_ERR(svn_client__get_youngest_common_ancestor(
- &ancestor, loc1, loc2, session, ctx, result_pool, scratch_pool));
-
- if (ancestor)
- {
- *ancestor_url = ancestor->url;
- *ancestor_rev = ancestor->rev;
- }
- else
- {
- *ancestor_url = NULL;
- *ancestor_rev = SVN_INVALID_REVNUM;
- }
- svn_pool_destroy(sesspool);
- return SVN_NO_ERROR;
-}
-
-
struct ra_ev2_baton {
/* The working copy context, from the client context. */
svn_wc_context_t *wc_ctx;
@@ -1080,6 +1093,7 @@ svn_client__ra_provide_base(svn_stream_t **contents,
/* The pristine contents refer to the BASE, or to the pristine of
a copy/move to this location. Fetch the correct revision. */
SVN_ERR(svn_wc__node_get_origin(NULL, revision, NULL, NULL, NULL, NULL,
+ NULL,
reb->wc_ctx, local_abspath, FALSE,
scratch_pool, scratch_pool));
}
@@ -1124,6 +1138,7 @@ svn_client__ra_provide_props(apr_hash_t **props,
/* The pristine props refer to the BASE, or to the pristine props of
a copy/move to this location. Fetch the correct revision. */
SVN_ERR(svn_wc__node_get_origin(NULL, revision, NULL, NULL, NULL, NULL,
+ NULL,
reb->wc_ctx, local_abspath, FALSE,
scratch_pool, scratch_pool));
}