You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/04/23 14:33:03 UTC
svn commit: r1329209 [11/38] - in /subversion/branches/javahl-ra: ./ build/
build/ac-macros/ build/generator/ build/generator/templates/ build/win32/
contrib/client-side/emacs/ contrib/client-side/vim/
contrib/server-side/mod_dontdothat/ notes/ notes/a...
Modified: subversion/branches/javahl-ra/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/repos_diff.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_client/repos_diff.c Mon Apr 23 12:32:48 2012
@@ -47,6 +47,7 @@
#include "client.h"
+#include "private/svn_subr_private.h"
#include "private/svn_wc_private.h"
/* Overall crawler editor baton. */
@@ -418,17 +419,6 @@ remove_non_prop_changes(apr_hash_t *pris
}
}
-/* Get the props attached to a directory in the repository at BASE_REVISION. */
-static svn_error_t *
-get_dirprops_from_ra(struct dir_baton *b, svn_revnum_t base_revision)
-{
- return svn_ra_get_dir2(b->edit_baton->ra_session,
- NULL, NULL, &(b->pristine_props),
- b->path,
- base_revision,
- 0,
- b->pool);
-}
/* Get the empty file associated with the edit baton. This is cached so
* that it can be reused, all empty files are the same.
@@ -472,44 +462,91 @@ open_root(void *edit_baton,
struct edit_baton *eb = edit_baton;
struct dir_baton *b = make_dir_baton("", NULL, eb, FALSE, pool);
- SVN_ERR(get_dirprops_from_ra(b, base_revision));
+ SVN_ERR(svn_ra_get_dir2(eb->ra_session, NULL, NULL, &b->pristine_props,
+ b->path, base_revision, 0, pool));
*root_baton = b;
return SVN_NO_ERROR;
}
-/* Recursively walk tree rooted at DIR (at REVISION) in the repository,
+/* Compare a file being deleted against an empty file.
+ */
+static svn_error_t *
+diff_deleted_file(svn_wc_notify_state_t *state_p,
+ svn_boolean_t *tree_conflicted_p,
+ const char *path,
+ struct edit_baton *eb,
+ apr_pool_t *scratch_pool)
+{
+ struct file_baton *b = make_file_baton(path, FALSE, eb, scratch_pool);
+/* struct edit_baton *eb = b->edit_baton;*/
+ const char *mimetype1, *mimetype2;
+
+ if (eb->cancel_func)
+ SVN_ERR(eb->cancel_func(eb->cancel_baton));
+
+ if (eb->text_deltas)
+ SVN_ERR(get_file_from_ra(b, FALSE, scratch_pool));
+ else
+ SVN_ERR(get_empty_file(eb, &b->path_start_revision));
+ SVN_ERR(get_empty_file(eb, &b->path_end_revision));
+ get_file_mime_types(&mimetype1, &mimetype2, b);
+
+ SVN_ERR(eb->diff_callbacks->file_deleted(state_p, tree_conflicted_p,
+ b->path,
+ b->path_start_revision,
+ b->path_end_revision,
+ mimetype1, mimetype2,
+ b->pristine_props,
+ eb->diff_cmd_baton,
+ scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+/* Recursively walk tree rooted at DIR (at EB->revision) in the repository,
* reporting all children as deleted. Part of a workaround for issue 2333.
*
- * DIR is a repository path relative to the URL in RA_SESSION. REVISION
- * must be a valid revision number, not SVN_INVALID_REVNUM. EB is the
- * overall crawler editor baton. If CANCEL_FUNC is not NULL, then it
- * should refer to a cancellation function (along with CANCEL_BATON).
+ * DIR is a repository path relative to the URL in EB->ra_session. EB is
+ * the overall crawler editor baton. EB->revision must be a valid revision
+ * number, not SVN_INVALID_REVNUM. Use EB->cancel_func (if not null) with
+ * EB->cancel_baton for cancellation.
*/
/* ### TODO: Handle depth. */
static svn_error_t *
-diff_deleted_dir(const char *dir,
- svn_revnum_t revision,
- svn_ra_session_t *ra_session,
+diff_deleted_dir(svn_wc_notify_state_t *state_p,
+ svn_boolean_t *tree_conflicted_p,
+ const char *dir,
struct edit_baton *eb,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
apr_pool_t *pool)
{
apr_hash_t *dirents;
apr_pool_t *iterpool = svn_pool_create(pool);
apr_hash_index_t *hi;
- SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(eb->revision));
+
+ if (eb->cancel_func)
+ SVN_ERR(eb->cancel_func(eb->cancel_baton));
- if (cancel_func)
- SVN_ERR(cancel_func(cancel_baton));
+ SVN_ERR(eb->diff_callbacks->dir_deleted(
+ state_p, tree_conflicted_p, dir,
+ eb->diff_cmd_baton, pool));
+
+ /* The "old" dir will be skipped by the repository report. If required,
+ * crawl it recursively, diffing each file against the empty file. This
+ * is a workaround for issue 2333 "'svn diff URL1 URL2' not reverse of
+ * 'svn diff URL2 URL1'". */
+ if (! eb->walk_deleted_repos_dirs)
+ {
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
+ }
- SVN_ERR(svn_ra_get_dir2(ra_session,
+ SVN_ERR(svn_ra_get_dir2(eb->ra_session,
&dirents,
NULL, NULL,
dir,
- revision,
+ eb->revision,
SVN_DIRENT_KIND,
pool));
@@ -526,42 +563,12 @@ diff_deleted_dir(const char *dir,
if (dirent->kind == svn_node_file)
{
- struct file_baton *b;
- const char *mimetype1, *mimetype2;
-
- /* Compare a file being deleted against an empty file */
- b = make_file_baton(path, FALSE, eb, iterpool);
- if (eb->text_deltas)
- SVN_ERR(get_file_from_ra(b, FALSE, iterpool));
- else
- SVN_ERR(get_empty_file(eb, &b->path_start_revision));
-
- SVN_ERR(get_empty_file(b->edit_baton, &(b->path_end_revision)));
-
- get_file_mime_types(&mimetype1, &mimetype2, b);
-
- SVN_ERR(eb->diff_callbacks->file_deleted(
- NULL, NULL, b->path,
- b->path_start_revision,
- b->path_end_revision,
- mimetype1, mimetype2,
- b->pristine_props,
- b->edit_baton->diff_cmd_baton,
- iterpool));
+ SVN_ERR(diff_deleted_file(NULL, NULL, path, eb, iterpool));
}
if (dirent->kind == svn_node_dir)
{
- SVN_ERR(eb->diff_callbacks->dir_deleted(
- NULL, NULL, path,
- eb->diff_cmd_baton, iterpool));
- SVN_ERR(diff_deleted_dir(path,
- revision,
- ra_session,
- eb,
- cancel_func,
- cancel_baton,
- iterpool));
+ SVN_ERR(diff_deleted_dir(NULL, NULL, path, eb, iterpool));
}
}
@@ -599,51 +606,14 @@ delete_entry(const char *path,
{
case svn_node_file:
{
- const char *mimetype1, *mimetype2;
- struct file_baton *b;
-
- /* Compare a file being deleted against an empty file */
- b = make_file_baton(path, FALSE, eb, scratch_pool);
- if (eb->text_deltas)
- SVN_ERR(get_file_from_ra(b, FALSE, scratch_pool));
- else
- SVN_ERR(get_empty_file(eb, &b->path_start_revision));
-
- SVN_ERR(get_empty_file(b->edit_baton, &(b->path_end_revision)));
-
- get_file_mime_types(&mimetype1, &mimetype2, b);
-
- SVN_ERR(eb->diff_callbacks->file_deleted(
- &state, &tree_conflicted, b->path,
- b->path_start_revision,
- b->path_end_revision,
- mimetype1, mimetype2,
- b->pristine_props,
- b->edit_baton->diff_cmd_baton,
- scratch_pool));
-
+ SVN_ERR(diff_deleted_file(&state, &tree_conflicted, path, eb,
+ scratch_pool));
break;
}
case svn_node_dir:
{
- SVN_ERR(eb->diff_callbacks->dir_deleted(
- &state, &tree_conflicted,
- path,
- eb->diff_cmd_baton, scratch_pool));
-
- if (eb->walk_deleted_repos_dirs)
- {
- /* A workaround for issue 2333. The "old" dir will be
- skipped by the repository report. Crawl it recursively,
- diffing each file against the empty file. */
- SVN_ERR(diff_deleted_dir(path,
- eb->revision,
- eb->ra_session,
- eb,
- eb->cancel_func,
- eb->cancel_baton,
- scratch_pool));
- }
+ SVN_ERR(diff_deleted_dir(&state, &tree_conflicted, path, eb,
+ scratch_pool));
break;
}
default:
@@ -787,7 +757,8 @@ open_directory(const char *path,
return SVN_NO_ERROR;
}
- SVN_ERR(get_dirprops_from_ra(b, base_revision));
+ SVN_ERR(svn_ra_get_dir2(eb->ra_session, NULL, NULL, &b->pristine_props,
+ b->path, base_revision, 0, pool));
SVN_ERR(eb->diff_callbacks->dir_opened(
&b->tree_conflicted, &b->skip,
@@ -870,9 +841,8 @@ window_handler(svn_txdelta_window_t *win
if (!window)
{
- b->result_md5_checksum = svn_checksum__from_digest(b->result_digest,
- svn_checksum_md5,
- b->pool);
+ b->result_md5_checksum = svn_checksum__from_digest_md5(b->result_digest,
+ b->pool);
}
return SVN_NO_ERROR;
@@ -1328,6 +1298,105 @@ absent_file(const char *path,
return SVN_NO_ERROR;
}
+static svn_error_t *
+fetch_kind_func(svn_kind_t *kind,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *scratch_pool)
+{
+ struct edit_baton *eb = baton;
+ svn_node_kind_t node_kind;
+
+ if (!SVN_IS_VALID_REVNUM(base_revision))
+ base_revision = eb->revision;
+
+ SVN_ERR(svn_ra_check_path(eb->ra_session, path, base_revision, &node_kind,
+ scratch_pool));
+
+ *kind = svn__kind_from_node_kind(node_kind, FALSE);
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_props_func(apr_hash_t **props,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct edit_baton *eb = baton;
+ svn_node_kind_t node_kind;
+
+ if (!SVN_IS_VALID_REVNUM(base_revision))
+ base_revision = eb->revision;
+
+ SVN_ERR(svn_ra_check_path(eb->ra_session, path, base_revision, &node_kind,
+ scratch_pool));
+
+ if (node_kind == svn_node_file)
+ {
+ SVN_ERR(svn_ra_get_file(eb->ra_session, path, base_revision,
+ NULL, NULL, props, result_pool));
+ }
+ else if (node_kind == svn_node_dir)
+ {
+ apr_array_header_t *tmp_props;
+
+ SVN_ERR(svn_ra_get_dir2(eb->ra_session, NULL, NULL, props, path,
+ base_revision, 0 /* Dirent fields */,
+ result_pool));
+ tmp_props = svn_prop_hash_to_array(*props, result_pool);
+ SVN_ERR(svn_categorize_props(tmp_props, NULL, NULL, &tmp_props,
+ result_pool));
+ *props = svn_prop_array_to_hash(tmp_props, result_pool);
+ }
+ else
+ {
+ *props = apr_hash_make(result_pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_base_func(const char **filename,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct edit_baton *eb = baton;
+ svn_stream_t *fstream;
+ svn_error_t *err;
+
+ if (!SVN_IS_VALID_REVNUM(base_revision))
+ base_revision = eb->revision;
+
+ SVN_ERR(svn_stream_open_unique(&fstream, filename, NULL,
+ svn_io_file_del_on_pool_cleanup,
+ result_pool, scratch_pool));
+
+ err = svn_ra_get_file(eb->ra_session, path, base_revision,
+ fstream, NULL, NULL, scratch_pool);
+ if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
+ {
+ svn_error_clear(err);
+ SVN_ERR(svn_stream_close(fstream));
+
+ *filename = NULL;
+ return SVN_NO_ERROR;
+ }
+ else if (err)
+ return svn_error_trace(err);
+
+ SVN_ERR(svn_stream_close(fstream));
+
+ return SVN_NO_ERROR;
+}
+
/* Create a repository diff editor and baton. */
svn_error_t *
svn_client__get_diff_editor(const svn_delta_editor_t **editor,
@@ -1389,8 +1458,13 @@ svn_client__get_diff_editor(const svn_de
editor, edit_baton,
eb->pool));
+ shim_callbacks->fetch_kind_func = fetch_kind_func;
+ shim_callbacks->fetch_props_func = fetch_props_func;
+ shim_callbacks->fetch_base_func = fetch_base_func;
+ shim_callbacks->fetch_baton = eb;
+
SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton,
- shim_callbacks,
+ NULL, NULL, shim_callbacks,
result_pool, result_pool));
return SVN_NO_ERROR;
Modified: subversion/branches/javahl-ra/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/status.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_client/status.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_client/status.c Mon Apr 23 12:32:48 2012
@@ -374,7 +374,7 @@ svn_client_status5(svn_revnum_t *result_
SVN_ERR(svn_ra_has_capability(ra_session, &server_supports_depth,
SVN_RA_CAPABILITY_DEPTH, pool));
- SVN_ERR(svn_wc_get_status_editor5(&editor, &edit_baton, &set_locks_baton,
+ SVN_ERR(svn_wc__get_status_editor(&editor, &edit_baton, &set_locks_baton,
&edit_revision, ctx->wc_ctx,
dir_abspath, target_basename,
depth, get_all,
Modified: subversion/branches/javahl-ra/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/switch.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_client/switch.c Mon Apr 23 12:32:48 2012
@@ -197,20 +197,23 @@ switch_internal(svn_revnum_t *result_rev
### okay? */
if (! ignore_ancestry)
{
- const char *target_url, *yc_path;
- svn_revnum_t target_rev, yc_rev;
+ const char *target_url;
+ svn_revnum_t target_rev;
+ svn_client__pathrev_t *switch_loc, *target_loc, *yca;
+ SVN_ERR(svn_client__pathrev_create_with_session(
+ &switch_loc, ra_session, revnum, switch_rev_url, pool));
SVN_ERR(svn_wc__node_get_url(&target_url, ctx->wc_ctx, local_abspath,
pool, pool));
SVN_ERR(svn_wc__node_get_base_rev(&target_rev, ctx->wc_ctx,
local_abspath, pool));
+ SVN_ERR(svn_client__pathrev_create_with_session(
+ &target_loc, ra_session, target_rev, target_url, pool));
/* ### It would be nice if this function could reuse the existing
ra session instead of opening two for its own use. */
- SVN_ERR(svn_client__get_youngest_common_ancestor(&yc_path, &yc_rev,
- switch_rev_url, revnum,
- target_url, target_rev,
- ctx, pool));
- if (! (yc_path && SVN_IS_VALID_REVNUM(yc_rev)))
+ SVN_ERR(svn_client__get_youngest_common_ancestor(
+ &yca, switch_loc, target_loc, ctx, pool, pool));
+ if (! yca)
return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
_("'%s' shares no common ancestry with '%s'"),
switch_url, local_abspath);
@@ -228,7 +231,7 @@ switch_internal(svn_revnum_t *result_rev
SVN_ERR(svn_ra_get_session_url(ra_session, &dfb.anchor_url, pool));
dfb.target_revision = revnum;
- SVN_ERR(svn_wc_get_switch_editor4(&switch_editor, &switch_edit_baton,
+ SVN_ERR(svn_wc__get_switch_editor(&switch_editor, &switch_edit_baton,
&revnum, ctx->wc_ctx, anchor_abspath,
target, switch_rev_url, use_commit_times,
depth,
Modified: subversion/branches/javahl-ra/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/update.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_client/update.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_client/update.c Mon Apr 23 12:32:48 2012
@@ -370,7 +370,7 @@ update_internal(svn_revnum_t *result_rev
/* Fetch the update editor. If REVISION is invalid, that's okay;
the RA driver will call editor->set_target_revision later on. */
- SVN_ERR(svn_wc_get_update_editor4(&update_editor, &update_edit_baton,
+ SVN_ERR(svn_wc__get_update_editor(&update_editor, &update_edit_baton,
&revnum, ctx->wc_ctx, anchor_abspath,
target, use_commit_times, depth,
depth_is_sticky, allow_unver_obstructions,
Modified: subversion/branches/javahl-ra/subversion/libsvn_client/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/util.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_client/util.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_client/util.c Mon Apr 23 12:32:48 2012
@@ -41,6 +41,99 @@
#include "svn_private_config.h"
+svn_client__pathrev_t *
+svn_client__pathrev_create(const char *repos_root_url,
+ const char *repos_uuid,
+ svn_revnum_t rev,
+ const char *url,
+ apr_pool_t *result_pool)
+{
+ svn_client__pathrev_t *loc = apr_palloc(result_pool, sizeof(*loc));
+
+ SVN_ERR_ASSERT_NO_RETURN(svn_path_is_url(repos_root_url));
+ SVN_ERR_ASSERT_NO_RETURN(svn_path_is_url(url));
+
+ loc->repos_root_url = apr_pstrdup(result_pool, repos_root_url);
+ loc->repos_uuid = apr_pstrdup(result_pool, repos_uuid);
+ loc->rev = rev;
+ loc->url = apr_pstrdup(result_pool, url);
+ return loc;
+}
+
+svn_client__pathrev_t *
+svn_client__pathrev_create_with_relpath(const char *repos_root_url,
+ const char *repos_uuid,
+ svn_revnum_t rev,
+ const char *relpath,
+ apr_pool_t *result_pool)
+{
+ SVN_ERR_ASSERT_NO_RETURN(svn_relpath_is_canonical(relpath));
+
+ return svn_client__pathrev_create(
+ repos_root_url, repos_uuid, rev,
+ svn_path_url_add_component2(repos_root_url, relpath, result_pool),
+ result_pool);
+}
+
+svn_error_t *
+svn_client__pathrev_create_with_session(svn_client__pathrev_t **pathrev_p,
+ svn_ra_session_t *ra_session,
+ svn_revnum_t rev,
+ const char *url,
+ apr_pool_t *result_pool)
+{
+ svn_client__pathrev_t *pathrev = apr_palloc(result_pool, sizeof(*pathrev));
+
+ SVN_ERR_ASSERT(svn_path_is_url(url));
+
+ SVN_ERR(svn_ra_get_repos_root2(ra_session, &pathrev->repos_root_url,
+ result_pool));
+ SVN_ERR(svn_ra_get_uuid2(ra_session, &pathrev->repos_uuid, result_pool));
+ pathrev->rev = rev;
+ pathrev->url = apr_pstrdup(result_pool, url);
+ *pathrev_p = pathrev;
+ return SVN_NO_ERROR;
+}
+
+svn_client__pathrev_t *
+svn_client__pathrev_dup(const svn_client__pathrev_t *pathrev,
+ apr_pool_t *result_pool)
+{
+ return svn_client__pathrev_create(
+ pathrev->repos_root_url, pathrev->repos_uuid,
+ pathrev->rev, pathrev->url, result_pool);
+}
+
+svn_client__pathrev_t *
+svn_client__pathrev_join_relpath(const svn_client__pathrev_t *pathrev,
+ const char *relpath,
+ apr_pool_t *result_pool)
+{
+ return svn_client__pathrev_create(
+ pathrev->repos_root_url, pathrev->repos_uuid, pathrev->rev,
+ svn_path_url_add_component2(pathrev->url, relpath, result_pool),
+ result_pool);
+}
+
+const char *
+svn_client__pathrev_relpath(const svn_client__pathrev_t *pathrev,
+ apr_pool_t *result_pool)
+{
+ return svn_uri_skip_ancestor(pathrev->repos_root_url, pathrev->url,
+ result_pool);
+}
+
+const char *
+svn_client__pathrev_fspath(const svn_client__pathrev_t *pathrev,
+ apr_pool_t *result_pool)
+{
+ return svn_fspath__canonicalize(svn_uri_skip_ancestor(
+ pathrev->repos_root_url, pathrev->url,
+ result_pool),
+ result_pool);
+}
+
+
svn_client_commit_item3_t *
svn_client_commit_item3_create(apr_pool_t *pool)
{
@@ -90,10 +183,7 @@ svn_client__path_relative_to_root(const
/* If we have a WC path... */
if (! svn_path_is_url(abspath_or_url))
{
- /* ...fetch its entry, and attempt to get both its full URL and
- repository root URL. If we can't get REPOS_ROOT from the WC
- entry, we'll get it from the RA layer.*/
-
+ /* ... query it directly. */
SVN_ERR(svn_wc__node_get_repos_relpath(&repos_relpath,
wc_ctx,
abspath_or_url,
@@ -142,6 +232,37 @@ svn_client__path_relative_to_root(const
}
svn_error_t *
+svn_client__wc_node_get_origin(svn_client__pathrev_t **origin_p,
+ const char *wc_abspath,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *relpath;
+
+ *origin_p = apr_palloc(result_pool, sizeof(**origin_p));
+
+ SVN_ERR(svn_wc__node_get_origin(NULL /* is_copy */,
+ &(*origin_p)->rev,
+ &relpath,
+ &(*origin_p)->repos_root_url,
+ &(*origin_p)->repos_uuid,
+ NULL, ctx->wc_ctx, wc_abspath,
+ FALSE /* scan_deleted */,
+ result_pool, scratch_pool));
+ if ((*origin_p)->repos_root_url && relpath)
+ {
+ (*origin_p)->url = svn_path_url_add_component2(
+ (*origin_p)->repos_root_url, relpath, result_pool);
+ }
+ else
+ {
+ *origin_p = NULL;
+ }
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_client_get_repos_root(const char **repos_root,
const char **repos_uuid,
const char *abspath_or_url,
@@ -240,3 +361,126 @@ svn_client__assert_homogeneous_target_ty
return SVN_NO_ERROR;
}
+
+struct shim_callbacks_baton
+{
+ svn_wc_context_t *wc_ctx;
+ apr_hash_t *relpath_map;
+};
+
+static svn_error_t *
+fetch_props_func(apr_hash_t **props,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct shim_callbacks_baton *scb = baton;
+ const char *local_abspath;
+
+ local_abspath = apr_hash_get(scb->relpath_map, path, APR_HASH_KEY_STRING);
+ if (!local_abspath)
+ {
+ *props = apr_hash_make(result_pool);
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(svn_wc_get_pristine_props(props, scb->wc_ctx, local_abspath,
+ result_pool, scratch_pool));
+
+ if (!*props)
+ *props = apr_hash_make(result_pool);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_kind_func(svn_kind_t *kind,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *scratch_pool)
+{
+ struct shim_callbacks_baton *scb = baton;
+ svn_node_kind_t node_kind;
+ const char *local_abspath;
+
+ local_abspath = apr_hash_get(scb->relpath_map, path, APR_HASH_KEY_STRING);
+ if (!local_abspath)
+ {
+ *kind = svn_kind_unknown;
+ return SVN_NO_ERROR;
+ }
+
+ SVN_ERR(svn_wc_read_kind(&node_kind, scb->wc_ctx, local_abspath, FALSE,
+ scratch_pool));
+ *kind = svn__kind_from_node_kind(node_kind, FALSE);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+fetch_base_func(const char **filename,
+ void *baton,
+ const char *path,
+ svn_revnum_t base_revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct shim_callbacks_baton *scb = baton;
+ const char *local_abspath;
+ svn_stream_t *pristine_stream;
+ svn_stream_t *temp_stream;
+ svn_error_t *err;
+
+ local_abspath = apr_hash_get(scb->relpath_map, path, APR_HASH_KEY_STRING);
+ if (!local_abspath)
+ {
+ *filename = NULL;
+ return SVN_NO_ERROR;
+ }
+
+ err = svn_wc_get_pristine_contents2(&pristine_stream, scb->wc_ctx,
+ local_abspath, scratch_pool,
+ scratch_pool);
+ if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+ {
+ svn_error_clear(err);
+ *filename = NULL;
+ return SVN_NO_ERROR;
+ }
+ else if (err)
+ return svn_error_trace(err);
+
+ SVN_ERR(svn_stream_open_unique(&temp_stream, filename, NULL,
+ svn_io_file_del_on_pool_cleanup,
+ result_pool, scratch_pool));
+ SVN_ERR(svn_stream_copy3(pristine_stream, temp_stream, NULL, NULL,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_delta_shim_callbacks_t *
+svn_client__get_shim_callbacks(svn_wc_context_t *wc_ctx,
+ apr_hash_t *relpath_map,
+ apr_pool_t *result_pool)
+{
+ svn_delta_shim_callbacks_t *callbacks =
+ svn_delta_shim_callbacks_default(result_pool);
+ struct shim_callbacks_baton *scb = apr_pcalloc(result_pool, sizeof(*scb));
+
+ scb->wc_ctx = wc_ctx;
+ if (relpath_map)
+ scb->relpath_map = relpath_map;
+ else
+ scb->relpath_map = apr_hash_make(result_pool);
+
+ callbacks->fetch_props_func = fetch_props_func;
+ callbacks->fetch_kind_func = fetch_kind_func;
+ callbacks->fetch_base_func = fetch_base_func;
+ callbacks->fetch_baton = scb;
+
+ return callbacks;
+}