summaryrefslogtreecommitdiff
path: root/subversion/libsvn_ra
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2015-03-18 13:33:26 +0000
committer <>2015-07-08 14:41:01 +0000
commitbb0ef45f7c46b0ae221b26265ef98a768c33f820 (patch)
tree98bae10dde41c746c51ae97ec4f879e330415aa7 /subversion/libsvn_ra
parent239dfafe71711b2f4c43d7b90a1228d7bdc5195e (diff)
downloadsubversion-tarball-bb0ef45f7c46b0ae221b26265ef98a768c33f820.tar.gz
Imported from /home/lorry/working-area/delta_subversion-tarball/subversion-1.8.13.tar.gz.subversion-1.8.13
Diffstat (limited to 'subversion/libsvn_ra')
-rw-r--r--subversion/libsvn_ra/compat.c114
-rw-r--r--subversion/libsvn_ra/debug_reporter.c4
-rw-r--r--subversion/libsvn_ra/deprecated.c108
-rw-r--r--subversion/libsvn_ra/deprecated.h60
-rw-r--r--subversion/libsvn_ra/editor.c339
-rw-r--r--subversion/libsvn_ra/ra_loader.c503
-rw-r--r--subversion/libsvn_ra/ra_loader.h122
-rw-r--r--subversion/libsvn_ra/util.c62
-rw-r--r--subversion/libsvn_ra/wrapper_template.h12
9 files changed, 1109 insertions, 215 deletions
diff --git a/subversion/libsvn_ra/compat.c b/subversion/libsvn_ra/compat.c
index ec3ff9d..b16bbef 100644
--- a/subversion/libsvn_ra/compat.c
+++ b/subversion/libsvn_ra/compat.c
@@ -23,6 +23,7 @@
#include <apr_pools.h>
+#include "svn_hash.h"
#include "svn_error.h"
#include "svn_pools.h"
#include "svn_sorts.h"
@@ -91,7 +92,7 @@ prev_log_path(const char **prev_path_p,
if (changed_paths)
{
/* See if PATH was explicitly changed in this revision. */
- change = apr_hash_get(changed_paths, path, APR_HASH_KEY_STRING);
+ change = svn_hash_gets(changed_paths, path);
if (change)
{
/* If PATH was not newly added in this revision, then it may or may
@@ -141,7 +142,7 @@ prev_log_path(const char **prev_path_p,
svn_sort__item_t item = APR_ARRAY_IDX(paths,
i - 1, svn_sort__item_t);
const char *ch_path = item.key;
- int len = strlen(ch_path);
+ size_t len = strlen(ch_path);
/* See if our path is the child of this change path. If
not, keep looking. */
@@ -154,7 +155,7 @@ prev_log_path(const char **prev_path_p,
path, to the change's copyfrom path. Otherwise, this
change isn't really interesting to us, and our search
continues. */
- change = apr_hash_get(changed_paths, ch_path, len);
+ change = item.value;
if (change->copyfrom_path)
{
if (action_p)
@@ -630,7 +631,6 @@ fr_log_message_receiver(void *baton,
{
struct fr_log_message_baton *lmb = baton;
struct rev *rev;
- apr_hash_index_t *hi;
rev = apr_palloc(lmb->pool, sizeof(*rev));
rev->revision = log_entry->revision;
@@ -639,17 +639,7 @@ fr_log_message_receiver(void *baton,
lmb->eldest = rev;
/* Duplicate log_entry revprops into rev->props */
- rev->props = apr_hash_make(lmb->pool);
- for (hi = apr_hash_first(pool, log_entry->revprops); hi;
- hi = apr_hash_next(hi))
- {
- void *val;
- const void *key;
-
- apr_hash_this(hi, &key, NULL, &val);
- apr_hash_set(rev->props, apr_pstrdup(lmb->pool, key), APR_HASH_KEY_STRING,
- svn_string_dup(val, lmb->pool));
- }
+ rev->props = svn_prop_hash_dup(log_entry->revprops, lmb->pool);
return prev_log_path(&lmb->path, &lmb->action,
&lmb->copyrev, log_entry->changed_paths2,
@@ -757,8 +747,9 @@ svn_ra__file_revs_from_log(svn_ra_session_t *ra_session,
/* Compute and send delta if client asked for it. */
if (delta_handler)
{
- /* Get the content delta. */
- svn_txdelta(&delta_stream, last_stream, stream, lastpool);
+ /* Get the content delta. Don't calculate checksums as we don't
+ * use them. */
+ svn_txdelta2(&delta_stream, last_stream, stream, FALSE, lastpool);
/* And send. */
SVN_ERR(svn_txdelta_send_txstream(delta_stream, delta_handler,
@@ -870,3 +861,92 @@ svn_ra__get_deleted_rev_from_log(svn_ra_session_t *session,
*revision_deleted = log_path_deleted_baton.revision_deleted;
return SVN_NO_ERROR;
}
+
+
+svn_error_t *
+svn_ra__get_inherited_props_walk(svn_ra_session_t *session,
+ const char *path,
+ svn_revnum_t revision,
+ apr_array_header_t **inherited_props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *repos_root_url;
+ const char *session_url;
+ const char *parent_url;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+ *inherited_props =
+ apr_array_make(result_pool, 1, sizeof(svn_prop_inherited_item_t *));
+
+ /* Walk to the root of the repository getting inherited
+ props for PATH. */
+ SVN_ERR(svn_ra_get_repos_root2(session, &repos_root_url, scratch_pool));
+ SVN_ERR(svn_ra_get_session_url(session, &session_url, scratch_pool));
+ parent_url = session_url;
+
+ while (strcmp(repos_root_url, parent_url))
+ {
+ apr_hash_index_t *hi;
+ apr_hash_t *parent_props;
+ apr_hash_t *final_hash = apr_hash_make(result_pool);
+ svn_error_t *err;
+
+ svn_pool_clear(iterpool);
+ parent_url = svn_uri_dirname(parent_url, scratch_pool);
+ SVN_ERR(svn_ra_reparent(session, parent_url, iterpool));
+ err = session->vtable->get_dir(session, NULL, NULL,
+ &parent_props, "",
+ revision, SVN_DIRENT_ALL,
+ iterpool);
+
+ /* If the user doesn't have read access to a parent path then
+ skip, but allow them to inherit from further up. */
+ if (err)
+ {
+ if ((err->apr_err == SVN_ERR_RA_NOT_AUTHORIZED)
+ || (err->apr_err == SVN_ERR_RA_DAV_FORBIDDEN))
+ {
+ svn_error_clear(err);
+ continue;
+ }
+ else
+ {
+ return svn_error_trace(err);
+ }
+ }
+
+ for (hi = apr_hash_first(scratch_pool, parent_props);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *name = svn__apr_hash_index_key(hi);
+ apr_ssize_t klen = svn__apr_hash_index_klen(hi);
+ svn_string_t *value = svn__apr_hash_index_val(hi);
+
+ if (svn_property_kind2(name) == svn_prop_regular_kind)
+ {
+ name = apr_pstrdup(result_pool, name);
+ value = svn_string_dup(value, result_pool);
+ apr_hash_set(final_hash, name, klen, value);
+ }
+ }
+
+ if (apr_hash_count(final_hash))
+ {
+ svn_prop_inherited_item_t *new_iprop =
+ apr_palloc(result_pool, sizeof(*new_iprop));
+ new_iprop->path_or_url = svn_uri_skip_ancestor(repos_root_url,
+ parent_url,
+ result_pool);
+ new_iprop->prop_hash = final_hash;
+ svn_sort__array_insert(&new_iprop, *inherited_props, 0);
+ }
+ }
+
+ /* Reparent session back to original URL. */
+ SVN_ERR(svn_ra_reparent(session, session_url, scratch_pool));
+
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
+}
diff --git a/subversion/libsvn_ra/debug_reporter.c b/subversion/libsvn_ra/debug_reporter.c
index 56248ac..00ec029 100644
--- a/subversion/libsvn_ra/debug_reporter.c
+++ b/subversion/libsvn_ra/debug_reporter.c
@@ -95,7 +95,7 @@ finish_report(void *report_baton,
apr_pool_t *pool)
{
struct report_baton *rb = report_baton;
- SVN_ERR(svn_stream_printf(rb->out, pool, "finish_report()\n"));
+ SVN_ERR(svn_stream_puts(rb->out, "finish_report()\n"));
SVN_ERR(rb->wrapped_reporter->finish_report(rb->wrapped_report_baton, pool));
return SVN_NO_ERROR;
}
@@ -105,7 +105,7 @@ abort_report(void *report_baton,
apr_pool_t *pool)
{
struct report_baton *rb = report_baton;
- SVN_ERR(svn_stream_printf(rb->out, pool, "abort_report()\n"));
+ SVN_ERR(svn_stream_puts(rb->out, "abort_report()\n"));
SVN_ERR(rb->wrapped_reporter->abort_report(rb->wrapped_report_baton, pool));
return SVN_NO_ERROR;
}
diff --git a/subversion/libsvn_ra/deprecated.c b/subversion/libsvn_ra/deprecated.c
index 6fd2442..b7e717e 100644
--- a/subversion/libsvn_ra/deprecated.c
+++ b/subversion/libsvn_ra/deprecated.c
@@ -26,6 +26,7 @@
deprecated functions in this file. */
#define SVN_DEPRECATED
+#include "svn_hash.h"
#include "svn_ra.h"
#include "svn_path.h"
#include "svn_compat.h"
@@ -33,6 +34,7 @@
#include "svn_pools.h"
#include "ra_loader.h"
+#include "deprecated.h"
#include "svn_private_config.h"
@@ -209,19 +211,18 @@ svn_error_t *svn_ra_get_commit_editor2(svn_ra_session_t *session,
const svn_delta_editor_t **editor,
void **edit_baton,
const char *log_msg,
- svn_commit_callback2_t callback,
- void *callback_baton,
+ svn_commit_callback2_t commit_callback,
+ void *commit_baton,
apr_hash_t *lock_tokens,
svn_boolean_t keep_locks,
apr_pool_t *pool)
{
apr_hash_t *revprop_table = apr_hash_make(pool);
if (log_msg)
- apr_hash_set(revprop_table, SVN_PROP_REVISION_LOG,
- APR_HASH_KEY_STRING,
- svn_string_create(log_msg, pool));
+ svn_hash_sets(revprop_table, SVN_PROP_REVISION_LOG,
+ svn_string_create(log_msg, pool));
return svn_ra_get_commit_editor3(session, editor, edit_baton, revprop_table,
- callback, callback_baton,
+ commit_callback, commit_baton,
lock_tokens, keep_locks, pool);
}
@@ -348,6 +349,29 @@ svn_error_t *svn_ra_get_file_revs(svn_ra_session_t *session,
handler2_baton, pool);
}
+svn_error_t *
+svn_ra_do_update2(svn_ra_session_t *session,
+ const svn_ra_reporter3_t **reporter,
+ void **report_baton,
+ svn_revnum_t revision_to_update_to,
+ const char *update_target,
+ svn_depth_t depth,
+ svn_boolean_t send_copyfrom_args,
+ const svn_delta_editor_t *update_editor,
+ void *update_baton,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(
+ svn_ra_do_update3(session,
+ reporter, report_baton,
+ revision_to_update_to, update_target,
+ depth,
+ send_copyfrom_args,
+ FALSE /* ignore_ancestry */,
+ update_editor, update_baton,
+ pool, pool));
+}
+
svn_error_t *svn_ra_do_update(svn_ra_session_t *session,
const svn_ra_reporter2_t **reporter,
void **report_baton,
@@ -368,8 +392,34 @@ svn_error_t *svn_ra_do_update(svn_ra_session_t *session,
revision_to_update_to, update_target,
SVN_DEPTH_INFINITY_OR_FILES(recurse),
FALSE, /* no copyfrom args */
+ FALSE /* ignore_ancestry */,
update_editor, update_baton,
- pool);
+ pool, pool);
+}
+
+
+svn_error_t *
+svn_ra_do_switch2(svn_ra_session_t *session,
+ const svn_ra_reporter3_t **reporter,
+ void **report_baton,
+ svn_revnum_t revision_to_switch_to,
+ const char *switch_target,
+ svn_depth_t depth,
+ const char *switch_url,
+ const svn_delta_editor_t *switch_editor,
+ void *switch_baton,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(
+ svn_ra_do_switch3(session,
+ reporter, report_baton,
+ revision_to_switch_to, switch_target,
+ depth,
+ switch_url,
+ FALSE /* send_copyfrom_args */,
+ TRUE /* ignore_ancestry */,
+ switch_editor, switch_baton,
+ pool, pool));
}
svn_error_t *svn_ra_do_switch(svn_ra_session_t *session,
@@ -392,8 +442,11 @@ svn_error_t *svn_ra_do_switch(svn_ra_session_t *session,
&(b->reporter3), &(b->reporter3_baton),
revision_to_switch_to, switch_target,
SVN_DEPTH_INFINITY_OR_FILES(recurse),
- switch_url, switch_editor, switch_baton,
- pool);
+ switch_url,
+ FALSE /* send_copyfrom_args */,
+ TRUE /* ignore_ancestry */,
+ switch_editor, switch_baton,
+ pool, pool);
}
svn_error_t *svn_ra_do_status(svn_ra_session_t *session,
@@ -417,3 +470,40 @@ svn_error_t *svn_ra_do_status(svn_ra_session_t *session,
SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse),
status_editor, status_baton, pool);
}
+
+svn_error_t *svn_ra_get_dir(svn_ra_session_t *session,
+ const char *path,
+ svn_revnum_t revision,
+ apr_hash_t **dirents,
+ svn_revnum_t *fetched_rev,
+ apr_hash_t **props,
+ apr_pool_t *pool)
+{
+ SVN_ERR_ASSERT(*path != '/');
+ return session->vtable->get_dir(session, dirents, fetched_rev, props,
+ path, revision, SVN_DIRENT_ALL, pool);
+}
+
+svn_error_t *
+svn_ra_local__deprecated_init(int abi_version,
+ apr_pool_t *pool,
+ apr_hash_t *hash)
+{
+ return svn_error_trace(svn_ra_local_init(abi_version, pool, hash));
+}
+
+svn_error_t *
+svn_ra_svn__deprecated_init(int abi_version,
+ apr_pool_t *pool,
+ apr_hash_t *hash)
+{
+ return svn_error_trace(svn_ra_svn_init(abi_version, pool, hash));
+}
+
+svn_error_t *
+svn_ra_serf__deprecated_init(int abi_version,
+ apr_pool_t *pool,
+ apr_hash_t *hash)
+{
+ return svn_error_trace(svn_ra_serf_init(abi_version, pool, hash));
+}
diff --git a/subversion/libsvn_ra/deprecated.h b/subversion/libsvn_ra/deprecated.h
new file mode 100644
index 0000000..205de16
--- /dev/null
+++ b/subversion/libsvn_ra/deprecated.h
@@ -0,0 +1,60 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ * @endcopyright
+ */
+
+
+
+#ifndef DEPRECATED_H
+#define DEPRECATED_H
+
+#include <apr_hash.h>
+
+#include "private/svn_editor.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Non-deprecated wrapper around svn_ra_local_init. */
+svn_error_t *
+svn_ra_local__deprecated_init(int abi_version,
+ apr_pool_t *pool,
+ apr_hash_t *hash);
+
+/* Non-deprecated wrapper around svn_ra_svn_init. */
+svn_error_t *
+svn_ra_svn__deprecated_init(int abi_version,
+ apr_pool_t *pool,
+ apr_hash_t *hash);
+
+/* Non-deprecated wrapper around svn_ra_serf_init. */
+svn_error_t *
+svn_ra_serf__deprecated_init(int abi_version,
+ apr_pool_t *pool,
+ apr_hash_t *hash);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DEPRECATED_H */
diff --git a/subversion/libsvn_ra/editor.c b/subversion/libsvn_ra/editor.c
new file mode 100644
index 0000000..ac969ca
--- /dev/null
+++ b/subversion/libsvn_ra/editor.c
@@ -0,0 +1,339 @@
+/*
+ * editor.c: compatibility editors
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#include <apr_pools.h>
+
+#include "svn_error.h"
+#include "svn_pools.h"
+#include "svn_ra.h"
+#include "svn_delta.h"
+#include "svn_dirent_uri.h"
+
+#include "private/svn_ra_private.h"
+#include "private/svn_delta_private.h"
+#include "private/svn_editor.h"
+
+#include "ra_loader.h"
+#include "svn_private_config.h"
+
+
+struct fp_baton {
+ svn_ra__provide_props_cb_t provide_props_cb;
+ void *cb_baton;
+};
+
+struct fb_baton {
+ svn_ra__provide_base_cb_t provide_base_cb;
+ void *cb_baton;
+};
+
+/* The shims currently want a callback that provides props for a given
+ REPOS_RELPATH at a given BASE_REVISION. However, the RA Ev2 interface
+ has a callback that provides properties for the REPOS_RELPATH from any
+ revision, which is returned along with the properties.
+
+ This is a little shim to map between the prototypes. The base revision
+ for the properties is discarded, and the requested revision (from the
+ shim code) is ignored.
+
+ The shim code needs to be updated to allow for an RA-style callback
+ to fetch properties. */
+static svn_error_t *
+fetch_props(apr_hash_t **props,
+ void *baton,
+ const char *repos_relpath,
+ svn_revnum_t base_revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct fp_baton *fpb = baton;
+ svn_revnum_t unused_revision;
+
+ /* Ignored: BASE_REVISION. */
+
+ return svn_error_trace(fpb->provide_props_cb(props, &unused_revision,
+ fpb->cb_baton,
+ repos_relpath,
+ result_pool, scratch_pool));
+}
+
+/* See note above regarding BASE_REVISION.
+ This also pulls down the entire contents of the file stream from the
+ RA layer and stores them in a local file, returning the path.
+*/
+static svn_error_t *
+fetch_base(const char **filename,
+ void *baton,
+ const char *repos_relpath,
+ svn_revnum_t base_revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct fb_baton *fbb = baton;
+ svn_revnum_t unused_revision;
+ svn_stream_t *contents;
+ svn_stream_t *file_stream;
+ const char *tmp_filename;
+
+ /* Ignored: BASE_REVISION. */
+
+ SVN_ERR(fbb->provide_base_cb(&contents, &unused_revision, fbb->cb_baton,
+ repos_relpath, result_pool, scratch_pool));
+
+ SVN_ERR(svn_stream_open_unique(&file_stream, &tmp_filename, NULL,
+ svn_io_file_del_on_pool_cleanup,
+ scratch_pool, scratch_pool));
+ SVN_ERR(svn_stream_copy3(contents, file_stream, NULL, NULL, scratch_pool));
+
+ *filename = apr_pstrdup(result_pool, tmp_filename);
+
+
+
+ return SVN_NO_ERROR;
+}
+
+
+
+svn_error_t *
+svn_ra__use_commit_shim(svn_editor_t **editor,
+ svn_ra_session_t *session,
+ apr_hash_t *revprop_table,
+ svn_commit_callback2_t commit_callback,
+ void *commit_baton,
+ apr_hash_t *lock_tokens,
+ svn_boolean_t keep_locks,
+ svn_ra__provide_base_cb_t provide_base_cb,
+ svn_ra__provide_props_cb_t provide_props_cb,
+ svn_ra__get_copysrc_kind_cb_t get_copysrc_kind_cb,
+ void *cb_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const svn_delta_editor_t *deditor;
+ void *dedit_baton;
+ struct svn_delta__extra_baton *exb;
+ svn_delta__unlock_func_t unlock_func;
+ void *unlock_baton;
+ const char *repos_root;
+ const char *session_url;
+ const char *base_relpath;
+ svn_boolean_t *found_abs_paths;
+ struct fp_baton *fpb;
+
+ /* NOTE: PROVIDE_BASE_CB is currently unused by this shim. In the future,
+ we can pass it to the underlying Ev2/Ev1 shim to produce better
+ apply_txdelta drives (ie. against a base rather than <empty>). */
+
+ /* Fetch the RA provider's Ev1 commit editor. */
+ SVN_ERR(session->vtable->get_commit_editor(session, &deditor, &dedit_baton,
+ revprop_table,
+ commit_callback, commit_baton,
+ lock_tokens, keep_locks,
+ result_pool));
+
+ /* Get or calculate the appropriate repos root and base relpath. */
+ SVN_ERR(svn_ra_get_repos_root2(session, &repos_root, scratch_pool));
+ SVN_ERR(svn_ra_get_session_url(session, &session_url, scratch_pool));
+ base_relpath = svn_uri_skip_ancestor(repos_root, session_url, scratch_pool);
+
+ /* We will assume that when the underlying Ev1 editor is finally driven
+ by the shim, that we will not need to prepend "/" to the paths. Place
+ this on the heap because it is examined much later. Set to FALSE. */
+ found_abs_paths = apr_pcalloc(result_pool, sizeof(*found_abs_paths));
+
+ /* The PROVIDE_PROPS_CB callback does not match what the shims want.
+ Let's jigger things around a little bit here. */
+ fpb = apr_palloc(result_pool, sizeof(*fpb));
+ fpb->provide_props_cb = provide_props_cb;
+ fpb->cb_baton = cb_baton;
+
+ /* Create the Ev2 editor from the Ev1 editor provided by the RA layer.
+
+ Note: GET_COPYSRC_KIND_CB is compatible in type/semantics with the
+ shim's FETCH_KIND_FUNC parameter. */
+ SVN_ERR(svn_delta__editor_from_delta(editor, &exb,
+ &unlock_func, &unlock_baton,
+ deditor, dedit_baton,
+ found_abs_paths,
+ repos_root, base_relpath,
+ cancel_func, cancel_baton,
+ get_copysrc_kind_cb, cb_baton,
+ fetch_props, fpb,
+ result_pool, scratch_pool));
+
+ /* Note: UNLOCK_FUNC and UNLOCK_BATON are unused during commit drives.
+ We can safely drop them on the floor. */
+
+ /* Since we're (currently) just wrapping an existing Ev1 editor, we have
+ to call any start_edit handler it may provide (the shim uses this to
+ invoke Ev1's open_root callback). We've got a couple of options to do
+ so: Implement a wrapper editor and call the start_edit callback upon
+ the first invocation of any of the underlying editor's functions; or,
+ just assume our consumer is going to eventually use the editor it is
+ asking for, and call the start edit callback now. For simplicity's
+ sake, we do the latter. */
+ if (exb->start_edit)
+ {
+ /* Most commit drives pass SVN_INVALID_REVNUM for the revision.
+ All calls to svn_delta_path_driver() pass SVN_INVALID_REVNUM,
+ so this is fine for any commits done via that function.
+
+ Notably, the PROPSET command passes a specific revision. Before
+ PROPSET can use the RA Ev2 interface, we may need to make this
+ revision a parameter.
+ ### what are the exact semantics? what is the meaning of the
+ ### revision passed to the Ev1->open_root() callback? */
+ SVN_ERR(exb->start_edit(exb->baton, SVN_INVALID_REVNUM));
+ }
+
+ /* Note: EXB also contains a TARGET_REVISION function, but that is not
+ used during commit operations. We can safely ignore it. (ie. it is
+ in EXB for use by paired-shims) */
+
+ return SVN_NO_ERROR;
+}
+
+
+struct wrapped_replay_baton_t {
+ svn_ra__replay_revstart_ev2_callback_t revstart_func;
+ svn_ra__replay_revfinish_ev2_callback_t revfinish_func;
+ void *replay_baton;
+
+ svn_ra_session_t *session;
+
+ svn_ra__provide_base_cb_t provide_base_cb;
+ svn_ra__provide_props_cb_t provide_props_cb;
+ void *cb_baton;
+
+ /* This will be populated by the revstart wrapper. */
+ svn_editor_t *editor;
+};
+
+static svn_error_t *
+revstart_func_wrapper(svn_revnum_t revision,
+ void *replay_baton,
+ const svn_delta_editor_t **deditor,
+ void **dedit_baton,
+ apr_hash_t *rev_props,
+ apr_pool_t *result_pool)
+{
+ struct wrapped_replay_baton_t *wrb = replay_baton;
+ const char *repos_root;
+ const char *session_url;
+ const char *base_relpath;
+ svn_boolean_t *found_abs_paths;
+ struct fp_baton *fpb;
+ struct svn_delta__extra_baton *exb;
+
+ /* Get the Ev2 editor from the original revstart func. */
+ SVN_ERR(wrb->revstart_func(revision, wrb->replay_baton, &wrb->editor,
+ rev_props, result_pool));
+
+ /* Get or calculate the appropriate repos root and base relpath. */
+ SVN_ERR(svn_ra_get_repos_root2(wrb->session, &repos_root, result_pool));
+ SVN_ERR(svn_ra_get_session_url(wrb->session, &session_url, result_pool));
+ base_relpath = svn_uri_skip_ancestor(repos_root, session_url, result_pool);
+
+ /* We will assume that when the underlying Ev1 editor is finally driven
+ by the shim, that we will not need to prepend "/" to the paths. Place
+ this on the heap because it is examined much later. Set to FALSE. */
+ found_abs_paths = apr_pcalloc(result_pool, sizeof(*found_abs_paths));
+
+ /* The PROVIDE_PROPS_CB callback does not match what the shims want.
+ Let's jigger things around a little bit here. */
+ fpb = apr_palloc(result_pool, sizeof(*fpb));
+ fpb->provide_props_cb = wrb->provide_props_cb;
+ fpb->cb_baton = wrb->cb_baton;
+
+ /* Create the extra baton. */
+ exb = apr_pcalloc(result_pool, sizeof(*exb));
+
+ /* Create the Ev1 editor from the Ev2 editor provided by the RA layer.
+
+ Note: GET_COPYSRC_KIND_CB is compatible in type/semantics with the
+ shim's FETCH_KIND_FUNC parameter. */
+ SVN_ERR(svn_delta__delta_from_editor(deditor, dedit_baton, wrb->editor,
+ NULL, NULL,
+ found_abs_paths,
+ repos_root, base_relpath,
+ fetch_props, wrb->cb_baton,
+ fetch_base, wrb->cb_baton,
+ exb, result_pool));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+revfinish_func_wrapper(svn_revnum_t revision,
+ void *replay_baton,
+ const svn_delta_editor_t *editor,
+ void *edit_baton,
+ apr_hash_t *rev_props,
+ apr_pool_t *pool)
+{
+ struct wrapped_replay_baton_t *wrb = replay_baton;
+
+ SVN_ERR(wrb->revfinish_func(revision, replay_baton, wrb->editor, rev_props,
+ pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_ra__use_replay_range_shim(svn_ra_session_t *session,
+ svn_revnum_t start_revision,
+ svn_revnum_t end_revision,
+ svn_revnum_t low_water_mark,
+ svn_boolean_t send_deltas,
+ svn_ra__replay_revstart_ev2_callback_t revstart_func,
+ svn_ra__replay_revfinish_ev2_callback_t revfinish_func,
+ void *replay_baton,
+ svn_ra__provide_base_cb_t provide_base_cb,
+ svn_ra__provide_props_cb_t provide_props_cb,
+ void *cb_baton,
+ apr_pool_t *scratch_pool)
+{
+ /* The basic strategy here is to wrap the callback start and finish
+ functions to appropriately return an Ev1 editor which is itself wrapped
+ from the Ev2 one the provided callbacks will give us. */
+
+ struct wrapped_replay_baton_t *wrb = apr_pcalloc(scratch_pool, sizeof(*wrb));
+
+ wrb->revstart_func = revstart_func;
+ wrb->revfinish_func = revfinish_func;
+ wrb->replay_baton = replay_baton;
+ wrb->session = session;
+
+ wrb->provide_base_cb = provide_base_cb;
+ wrb->provide_props_cb = provide_props_cb;
+ wrb->cb_baton = cb_baton;
+
+ return svn_error_trace(svn_ra_replay_range(session, start_revision,
+ end_revision, low_water_mark,
+ send_deltas,
+ revstart_func_wrapper,
+ revfinish_func_wrapper,
+ wrb, scratch_pool));
+}
diff --git a/subversion/libsvn_ra/ra_loader.c b/subversion/libsvn_ra/ra_loader.c
index b796a80..d9cb96b 100644
--- a/subversion/libsvn_ra/ra_loader.c
+++ b/subversion/libsvn_ra/ra_loader.c
@@ -33,6 +33,7 @@
#include <apr_hash.h>
#include <apr_uri.h>
+#include "svn_hash.h"
#include "svn_version.h"
#include "svn_types.h"
#include "svn_error.h"
@@ -43,27 +44,17 @@
#include "svn_xml.h"
#include "svn_path.h"
#include "svn_dso.h"
+#include "svn_props.h"
+#include "svn_sorts.h"
+
#include "svn_config.h"
#include "ra_loader.h"
+#include "deprecated.h"
#include "private/svn_ra_private.h"
#include "svn_private_config.h"
-/* ### This file maps URL schemes to particular RA libraries.
- ### Currently, the only pair of RA libraries which support the same
- ### protocols are neon and serf. svn_ra_open3 makes the assumption
- ### that this is the case; that their 'schemes' fields are both
- ### dav_schemes; and that "neon" is listed first.
-
- ### Users can choose which dav library to use with the http-library
- ### preference in .subversion/servers; however, it is ignored by
- ### any code which uses the pre-1.2 API svn_ra_get_ra_library
- ### instead of svn_ra_open. */
-
-#if defined(SVN_HAVE_NEON) && defined(SVN_HAVE_SERF)
-#define CHOOSABLE_DAV_MODULE
-#endif
/* These are the URI schemes that the respective libraries *may* support.
@@ -85,20 +76,11 @@ static const struct ra_lib_defn {
svn_ra_init_func_t compat_initfunc;
} ra_libraries[] = {
{
- "neon",
- dav_schemes,
-#ifdef SVN_LIBSVN_CLIENT_LINKS_RA_NEON
- svn_ra_neon__init,
- svn_ra_dav_init
-#endif
- },
-
- {
"svn",
svn_schemes,
#ifdef SVN_LIBSVN_CLIENT_LINKS_RA_SVN
svn_ra_svn__init,
- svn_ra_svn_init
+ svn_ra_svn__deprecated_init
#endif
},
@@ -107,7 +89,7 @@ static const struct ra_lib_defn {
local_schemes,
#ifdef SVN_LIBSVN_CLIENT_LINKS_RA_LOCAL
svn_ra_local__init,
- svn_ra_local_init
+ svn_ra_local__deprecated_init
#endif
},
@@ -116,7 +98,7 @@ static const struct ra_lib_defn {
dav_schemes,
#ifdef SVN_LIBSVN_CLIENT_LINKS_RA_SERF
svn_ra_serf__init,
- svn_ra_serf_init
+ svn_ra_serf__deprecated_init
#endif
},
@@ -159,8 +141,8 @@ load_ra_module(svn_ra__init_func_t *func,
const char *compat_funcname;
apr_status_t status;
- libname = apr_psprintf(pool, "libsvn_ra_%s-%d.so.0",
- ra_name, SVN_VER_MAJOR);
+ libname = apr_psprintf(pool, "libsvn_ra_%s-%d.so.%d",
+ ra_name, SVN_VER_MAJOR, SVN_SOVERSION);
funcname = apr_psprintf(pool, "svn_ra_%s__init", ra_name);
compat_funcname = apr_psprintf(pool, "svn_ra_%s_init", ra_name);
@@ -201,14 +183,13 @@ load_ra_module(svn_ra__init_func_t *func,
return SVN_NO_ERROR;
}
-/* If DEFN may support URL, return the scheme. Else, return NULL. */
+/* If SCHEMES contains URL, return the scheme. Else, return NULL. */
static const char *
-has_scheme_of(const struct ra_lib_defn *defn, const char *url)
+has_scheme_of(const char * const *schemes, const char *url)
{
- const char * const *schemes;
apr_size_t len;
- for (schemes = defn->schemes; *schemes != NULL; ++schemes)
+ for ( ; *schemes != NULL; ++schemes)
{
const char *scheme = *schemes;
len = strlen(scheme);
@@ -339,8 +320,7 @@ svn_error_t *svn_ra_open4(svn_ra_session_t **session_p,
if (config)
{
/* Grab the 'servers' config. */
- servers = apr_hash_get(config, SVN_CONFIG_CATEGORY_SERVERS,
- APR_HASH_KEY_STRING);
+ servers = svn_hash_gets(config, SVN_CONFIG_CATEGORY_SERVERS);
if (servers)
{
/* First, look in the global section. */
@@ -414,8 +394,7 @@ svn_error_t *svn_ra_open4(svn_ra_session_t **session_p,
SVN_CONFIG_OPTION_HTTP_LIBRARY,
DEFAULT_HTTP_LIBRARY);
- if (strcmp(http_library, "neon") != 0 &&
- strcmp(http_library, "serf") != 0)
+ if (strcmp(http_library, "serf") != 0)
return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL,
_("Invalid config: unknown HTTP library "
"'%s'"),
@@ -454,7 +433,7 @@ svn_error_t *svn_ra_open4(svn_ra_session_t **session_p,
{
const char *scheme;
- if ((scheme = has_scheme_of(defn, repos_URL)))
+ if ((scheme = has_scheme_of(defn->schemes, repos_URL)))
{
svn_ra__init_func_t initfunc = defn->initfunc;
@@ -475,6 +454,11 @@ svn_error_t *svn_ra_open4(svn_ra_session_t **session_p,
SVN_ERR(check_ra_version(vtable->get_version(), scheme));
+ if (! has_scheme_of(vtable->get_schemes(sesspool), repos_URL))
+ /* Library doesn't support the scheme at runtime. */
+ continue;
+
+
break;
}
}
@@ -486,6 +470,8 @@ svn_error_t *svn_ra_open4(svn_ra_session_t **session_p,
/* Create the session object. */
session = apr_pcalloc(sesspool, sizeof(*session));
+ session->cancel_func = callbacks->cancel_func;
+ session->cancel_baton = callback_baton;
session->vtable = vtable;
session->pool = sesspool;
@@ -570,19 +556,13 @@ svn_error_t *svn_ra_get_path_relative_to_session(svn_ra_session_t *session,
apr_pool_t *pool)
{
const char *sess_url;
+
SVN_ERR(session->vtable->get_session_url(session, &sess_url, pool));
- if (strcmp(sess_url, url) == 0)
- {
- *rel_path = "";
- }
- else
- {
- *rel_path = svn_uri__is_child(sess_url, url, pool);
- if (! *rel_path)
- return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
- _("'%s' isn't a child of session URL '%s'"),
- url, sess_url);
- }
+ *rel_path = svn_uri_skip_ancestor(sess_url, url, pool);
+ if (! *rel_path)
+ return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
+ _("'%s' isn't a child of session URL '%s'"),
+ url, sess_url);
return SVN_NO_ERROR;
}
@@ -592,21 +572,14 @@ svn_error_t *svn_ra_get_path_relative_to_root(svn_ra_session_t *session,
apr_pool_t *pool)
{
const char *root_url;
- SVN_ERR(session->vtable->get_repos_root(session, &root_url, pool));
- if (strcmp(root_url, url) == 0)
- {
- *rel_path = "";
- }
- else
- {
- *rel_path = svn_uri__is_child(root_url, url, pool);
- if (! *rel_path)
- return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
- _("'%s' isn't a child of repository root "
- "URL '%s'"),
- url, root_url);
- }
+ SVN_ERR(session->vtable->get_repos_root(session, &root_url, pool));
+ *rel_path = svn_uri_skip_ancestor(root_url, url, pool);
+ if (! *rel_path)
+ return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
+ _("'%s' isn't a child of repository root "
+ "URL '%s'"),
+ url, root_url);
return SVN_NO_ERROR;
}
@@ -699,30 +672,56 @@ commit_callback_wrapper(const svn_commit_info_t *commit_info,
return ccwb->original_callback(ci, ccwb->original_baton, pool);
}
+
+/* Some RA layers do not correctly fill in REPOS_ROOT in commit_info, or
+ they are third-party layers conforming to an older commit_info structure.
+ Interpose a utility function to ensure the field is valid. */
+static void
+remap_commit_callback(svn_commit_callback2_t *callback,
+ void **callback_baton,
+ svn_ra_session_t *session,
+ svn_commit_callback2_t original_callback,
+ void *original_baton,
+ apr_pool_t *result_pool)
+{
+ if (original_callback == NULL)
+ {
+ *callback = NULL;
+ *callback_baton = NULL;
+ }
+ else
+ {
+ /* Allocate this in RESULT_POOL, since the callback will be called
+ long after this function has returned. */
+ struct ccw_baton *ccwb = apr_palloc(result_pool, sizeof(*ccwb));
+
+ ccwb->session = session;
+ ccwb->original_callback = original_callback;
+ ccwb->original_baton = original_baton;
+
+ *callback = commit_callback_wrapper;
+ *callback_baton = ccwb;
+ }
+}
+
+
svn_error_t *svn_ra_get_commit_editor3(svn_ra_session_t *session,
const svn_delta_editor_t **editor,
void **edit_baton,
apr_hash_t *revprop_table,
- svn_commit_callback2_t callback,
- void *callback_baton,
+ svn_commit_callback2_t commit_callback,
+ void *commit_baton,
apr_hash_t *lock_tokens,
svn_boolean_t keep_locks,
apr_pool_t *pool)
{
- /* Allocate this in a pool, since the callback will be called long after
- this function as returned. */
- struct ccw_baton *ccwb = apr_palloc(pool, sizeof(*ccwb));
-
- ccwb->original_callback = callback;
- ccwb->original_baton = callback_baton;
- ccwb->session = session;
+ remap_commit_callback(&commit_callback, &commit_baton,
+ session, commit_callback, commit_baton,
+ pool);
return session->vtable->get_commit_editor(session, editor, edit_baton,
revprop_table,
- callback
- ? commit_callback_wrapper
- : NULL,
- callback ? ccwb : NULL,
+ commit_callback, commit_baton,
lock_tokens, keep_locks, pool);
}
@@ -734,24 +733,11 @@ svn_error_t *svn_ra_get_file(svn_ra_session_t *session,
apr_hash_t **props,
apr_pool_t *pool)
{
- SVN_ERR_ASSERT(*path != '/');
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
return session->vtable->get_file(session, path, revision, stream,
fetched_rev, props, pool);
}
-svn_error_t *svn_ra_get_dir(svn_ra_session_t *session,
- const char *path,
- svn_revnum_t revision,
- apr_hash_t **dirents,
- svn_revnum_t *fetched_rev,
- apr_hash_t **props,
- apr_pool_t *pool)
-{
- SVN_ERR_ASSERT(*path != '/');
- return session->vtable->get_dir(session, dirents, fetched_rev, props,
- path, revision, SVN_DIRENT_ALL, pool);
-}
-
svn_error_t *svn_ra_get_dir2(svn_ra_session_t *session,
apr_hash_t **dirents,
svn_revnum_t *fetched_rev,
@@ -761,7 +747,7 @@ svn_error_t *svn_ra_get_dir2(svn_ra_session_t *session,
apr_uint32_t dirent_fields,
apr_pool_t *pool)
{
- SVN_ERR_ASSERT(*path != '/');
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
return session->vtable->get_dir(session, dirents, fetched_rev, props,
path, revision, dirent_fields, pool);
}
@@ -781,7 +767,7 @@ svn_error_t *svn_ra_get_mergeinfo(svn_ra_session_t *session,
for (i = 0; i < paths->nelts; i++)
{
const char *path = APR_ARRAY_IDX(paths, i, const char *);
- SVN_ERR_ASSERT(*path != '/');
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
}
/* Check server Merge Tracking capability. */
@@ -797,16 +783,19 @@ svn_error_t *svn_ra_get_mergeinfo(svn_ra_session_t *session,
include_descendants, pool);
}
-svn_error_t *svn_ra_do_update2(svn_ra_session_t *session,
- const svn_ra_reporter3_t **reporter,
- void **report_baton,
- svn_revnum_t revision_to_update_to,
- const char *update_target,
- svn_depth_t depth,
- svn_boolean_t send_copyfrom_args,
- const svn_delta_editor_t *update_editor,
- void *update_baton,
- apr_pool_t *pool)
+svn_error_t *
+svn_ra_do_update3(svn_ra_session_t *session,
+ const svn_ra_reporter3_t **reporter,
+ void **report_baton,
+ svn_revnum_t revision_to_update_to,
+ const char *update_target,
+ svn_depth_t depth,
+ svn_boolean_t send_copyfrom_args,
+ svn_boolean_t ignore_ancestry,
+ const svn_delta_editor_t *update_editor,
+ void *update_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
SVN_ERR_ASSERT(svn_path_is_empty(update_target)
|| svn_path_is_single_path_component(update_target));
@@ -814,28 +803,37 @@ svn_error_t *svn_ra_do_update2(svn_ra_session_t *session,
reporter, report_baton,
revision_to_update_to, update_target,
depth, send_copyfrom_args,
+ ignore_ancestry,
update_editor, update_baton,
- pool);
+ result_pool, scratch_pool);
}
-svn_error_t *svn_ra_do_switch2(svn_ra_session_t *session,
- const svn_ra_reporter3_t **reporter,
- void **report_baton,
- svn_revnum_t revision_to_switch_to,
- const char *switch_target,
- svn_depth_t depth,
- const char *switch_url,
- const svn_delta_editor_t *switch_editor,
- void *switch_baton,
- apr_pool_t *pool)
+svn_error_t *
+svn_ra_do_switch3(svn_ra_session_t *session,
+ const svn_ra_reporter3_t **reporter,
+ void **report_baton,
+ svn_revnum_t revision_to_switch_to,
+ const char *switch_target,
+ svn_depth_t depth,
+ const char *switch_url,
+ svn_boolean_t send_copyfrom_args,
+ svn_boolean_t ignore_ancestry,
+ const svn_delta_editor_t *switch_editor,
+ void *switch_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
SVN_ERR_ASSERT(svn_path_is_empty(switch_target)
|| svn_path_is_single_path_component(switch_target));
return session->vtable->do_switch(session,
reporter, report_baton,
revision_to_switch_to, switch_target,
- depth, switch_url, switch_editor,
- switch_baton, pool);
+ depth, switch_url,
+ send_copyfrom_args,
+ ignore_ancestry,
+ switch_editor,
+ switch_baton,
+ result_pool, scratch_pool);
}
svn_error_t *svn_ra_do_status2(svn_ra_session_t *session,
@@ -869,6 +867,8 @@ svn_error_t *svn_ra_do_diff3(svn_ra_session_t *session,
void *diff_baton,
apr_pool_t *pool)
{
+ SVN_ERR_ASSERT(svn_path_is_empty(diff_target)
+ || svn_path_is_single_path_component(diff_target));
return session->vtable->do_diff(session,
reporter, report_baton,
revision, diff_target,
@@ -896,7 +896,7 @@ svn_error_t *svn_ra_get_log2(svn_ra_session_t *session,
for (i = 0; i < paths->nelts; i++)
{
const char *path = APR_ARRAY_IDX(paths, i, const char *);
- SVN_ERR_ASSERT(*path != '/');
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
}
}
@@ -915,7 +915,7 @@ svn_error_t *svn_ra_check_path(svn_ra_session_t *session,
svn_node_kind_t *kind,
apr_pool_t *pool)
{
- SVN_ERR_ASSERT(*path != '/');
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
return session->vtable->check_path(session, path, revision, kind, pool);
}
@@ -925,7 +925,7 @@ svn_error_t *svn_ra_stat(svn_ra_session_t *session,
svn_dirent_t **dirent,
apr_pool_t *pool)
{
- SVN_ERR_ASSERT(*path != '/');
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
return session->vtable->stat(session, path, revision, dirent, pool);
}
@@ -970,7 +970,7 @@ svn_error_t *svn_ra_get_locations(svn_ra_session_t *session,
{
svn_error_t *err;
- SVN_ERR_ASSERT(*path != '/');
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
err = session->vtable->get_locations(session, locations, path,
peg_revision, location_revisions, pool);
if (err && (err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED))
@@ -997,7 +997,7 @@ svn_ra_get_location_segments(svn_ra_session_t *session,
{
svn_error_t *err;
- SVN_ERR_ASSERT(*path != '/');
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
err = session->vtable->get_location_segments(session, path, peg_revision,
start_rev, end_rev,
receiver, receiver_baton, pool);
@@ -1025,11 +1025,18 @@ svn_error_t *svn_ra_get_file_revs2(svn_ra_session_t *session,
{
svn_error_t *err;
- SVN_ERR_ASSERT(*path != '/');
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
if (include_merged_revisions)
SVN_ERR(svn_ra__assert_mergeinfo_capable_server(session, NULL, pool));
+ if (start > end)
+ SVN_ERR(
+ svn_ra__assert_capable_server(session,
+ SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE,
+ NULL,
+ pool));
+
err = session->vtable->get_file_revs(session, path, start, end,
include_merged_revisions,
handler, handler_baton, pool);
@@ -1058,7 +1065,7 @@ svn_error_t *svn_ra_lock(svn_ra_session_t *session,
{
const char *path = svn__apr_hash_index_key(hi);
- SVN_ERR_ASSERT(*path != '/');
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
}
if (comment && ! svn_xml_is_xml_safe(comment, strlen(comment)))
@@ -1083,7 +1090,7 @@ svn_error_t *svn_ra_unlock(svn_ra_session_t *session,
{
const char *path = svn__apr_hash_index_key(hi);
- SVN_ERR_ASSERT(*path != '/');
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
}
return session->vtable->unlock(session, path_tokens, break_lock,
@@ -1095,7 +1102,7 @@ svn_error_t *svn_ra_get_lock(svn_ra_session_t *session,
const char *path,
apr_pool_t *pool)
{
- SVN_ERR_ASSERT(*path != '/');
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
return session->vtable->get_lock(session, lock, path, pool);
}
@@ -1105,7 +1112,7 @@ svn_error_t *svn_ra_get_locks2(svn_ra_session_t *session,
svn_depth_t depth,
apr_pool_t *pool)
{
- SVN_ERR_ASSERT(*path != '/');
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
SVN_ERR_ASSERT((depth == svn_depth_empty) ||
(depth == svn_depth_files) ||
(depth == svn_depth_immediates) ||
@@ -1134,6 +1141,58 @@ svn_error_t *svn_ra_replay(svn_ra_session_t *session,
}
svn_error_t *
+svn_ra__replay_ev2(svn_ra_session_t *session,
+ svn_revnum_t revision,
+ svn_revnum_t low_water_mark,
+ svn_boolean_t send_deltas,
+ svn_editor_t *editor,
+ apr_pool_t *scratch_pool)
+{
+ SVN__NOT_IMPLEMENTED();
+}
+
+static svn_error_t *
+replay_range_from_replays(svn_ra_session_t *session,
+ svn_revnum_t start_revision,
+ svn_revnum_t end_revision,
+ svn_revnum_t low_water_mark,
+ svn_boolean_t text_deltas,
+ svn_ra_replay_revstart_callback_t revstart_func,
+ svn_ra_replay_revfinish_callback_t revfinish_func,
+ void *replay_baton,
+ apr_pool_t *scratch_pool)
+{
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ svn_revnum_t rev;
+
+ for (rev = start_revision ; rev <= end_revision ; rev++)
+ {
+ const svn_delta_editor_t *editor;
+ void *edit_baton;
+ apr_hash_t *rev_props;
+
+ svn_pool_clear(iterpool);
+
+ SVN_ERR(svn_ra_rev_proplist(session, rev, &rev_props, iterpool));
+
+ SVN_ERR(revstart_func(rev, replay_baton,
+ &editor, &edit_baton,
+ rev_props,
+ iterpool));
+ SVN_ERR(svn_ra_replay(session, rev, low_water_mark,
+ text_deltas, editor, edit_baton,
+ iterpool));
+ SVN_ERR(revfinish_func(rev, replay_baton,
+ editor, edit_baton,
+ rev_props,
+ iterpool));
+ }
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_ra_replay_range(svn_ra_session_t *session,
svn_revnum_t start_revision,
svn_revnum_t end_revision,
@@ -1150,40 +1209,60 @@ svn_ra_replay_range(svn_ra_session_t *session,
revstart_func, revfinish_func,
replay_baton, pool);
- if (err && (err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED))
- {
- apr_pool_t *subpool = svn_pool_create(pool);
- svn_revnum_t rev;
-
- svn_error_clear(err);
- err = SVN_NO_ERROR;
+ if (!err || (err && (err->apr_err != SVN_ERR_RA_NOT_IMPLEMENTED)))
+ return svn_error_trace(err);
+
+ svn_error_clear(err);
+ return svn_error_trace(replay_range_from_replays(session, start_revision,
+ end_revision,
+ low_water_mark,
+ text_deltas,
+ revstart_func,
+ revfinish_func,
+ replay_baton, pool));
+}
- for (rev = start_revision ; rev <= end_revision ; rev++)
- {
- const svn_delta_editor_t *editor;
- void *edit_baton;
- apr_hash_t *rev_props;
-
- svn_pool_clear(subpool);
-
- SVN_ERR(svn_ra_rev_proplist(session, rev, &rev_props, subpool));
-
- SVN_ERR(revstart_func(rev, replay_baton,
- &editor, &edit_baton,
- rev_props,
- subpool));
- SVN_ERR(svn_ra_replay(session, rev, low_water_mark,
- text_deltas, editor, edit_baton,
- subpool));
- SVN_ERR(revfinish_func(rev, replay_baton,
- editor, edit_baton,
- rev_props,
- subpool));
- }
- svn_pool_destroy(subpool);
+svn_error_t *
+svn_ra__replay_range_ev2(svn_ra_session_t *session,
+ svn_revnum_t start_revision,
+ svn_revnum_t end_revision,
+ svn_revnum_t low_water_mark,
+ svn_boolean_t send_deltas,
+ svn_ra__replay_revstart_ev2_callback_t revstart_func,
+ svn_ra__replay_revfinish_ev2_callback_t revfinish_func,
+ void *replay_baton,
+ svn_ra__provide_base_cb_t provide_base_cb,
+ svn_ra__provide_props_cb_t provide_props_cb,
+ svn_ra__get_copysrc_kind_cb_t get_copysrc_kind_cb,
+ void *cb_baton,
+ apr_pool_t *scratch_pool)
+{
+ if (session->vtable->replay_range_ev2 == NULL)
+ {
+ /* The specific RA layer does not have an implementation. Use our
+ default shim over the normal replay editor. */
+
+ /* This will call the Ev1 replay range handler with modified
+ callbacks. */
+ return svn_error_trace(svn_ra__use_replay_range_shim(
+ session,
+ start_revision,
+ end_revision,
+ low_water_mark,
+ send_deltas,
+ revstart_func,
+ revfinish_func,
+ replay_baton,
+ provide_base_cb,
+ provide_props_cb,
+ cb_baton,
+ scratch_pool));
}
- return err;
+ return svn_error_trace(session->vtable->replay_range_ev2(
+ session, start_revision, end_revision,
+ low_water_mark, send_deltas, revstart_func,
+ revfinish_func, replay_baton, scratch_pool));
}
svn_error_t *svn_ra_has_capability(svn_ra_session_t *session,
@@ -1205,7 +1284,7 @@ svn_ra_get_deleted_rev(svn_ra_session_t *session,
svn_error_t *err;
/* Path must be relative. */
- SVN_ERR_ASSERT(*path != '/');
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
if (!SVN_IS_VALID_REVNUM(peg_revision))
return svn_error_createf(SVN_ERR_CLIENT_BAD_REVISION, NULL,
@@ -1221,8 +1300,7 @@ svn_ra_get_deleted_rev(svn_ra_session_t *session,
end_revision,
revision_deleted,
pool);
- if (err && (err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE /* serf */
- || err->apr_err == SVN_ERR_RA_NOT_IMPLEMENTED)) /* neon */
+ if (err && (err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE))
{
svn_error_clear(err);
@@ -1234,6 +1312,96 @@ svn_ra_get_deleted_rev(svn_ra_session_t *session,
return err;
}
+svn_error_t *
+svn_ra_get_inherited_props(svn_ra_session_t *session,
+ apr_array_header_t **iprops,
+ const char *path,
+ svn_revnum_t revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_boolean_t iprop_capable;
+
+ /* Path must be relative. */
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(path));
+
+ SVN_ERR(svn_ra_has_capability(session, &iprop_capable,
+ SVN_RA_CAPABILITY_INHERITED_PROPS,
+ scratch_pool));
+
+ if (iprop_capable)
+ {
+ SVN_ERR(session->vtable->get_inherited_props(session, iprops, path,
+ revision, result_pool,
+ scratch_pool));
+ }
+ else
+ {
+ /* Fallback for legacy servers. */
+ SVN_ERR(svn_ra__get_inherited_props_walk(session, path, revision, iprops,
+ result_pool, scratch_pool));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_ra__get_commit_ev2(svn_editor_t **editor,
+ svn_ra_session_t *session,
+ apr_hash_t *revprop_table,
+ svn_commit_callback2_t commit_callback,
+ void *commit_baton,
+ apr_hash_t *lock_tokens,
+ svn_boolean_t keep_locks,
+ svn_ra__provide_base_cb_t provide_base_cb,
+ svn_ra__provide_props_cb_t provide_props_cb,
+ svn_ra__get_copysrc_kind_cb_t get_copysrc_kind_cb,
+ void *cb_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ if (session->vtable->get_commit_ev2 == NULL)
+ {
+ /* The specific RA layer does not have an implementation. Use our
+ default shim over the normal commit editor. */
+
+ /* Remap for RA layers exposing Ev1. */
+ remap_commit_callback(&commit_callback, &commit_baton,
+ session, commit_callback, commit_baton,
+ result_pool);
+
+ return svn_error_trace(svn_ra__use_commit_shim(
+ editor,
+ session,
+ revprop_table,
+ commit_callback, commit_baton,
+ lock_tokens,
+ keep_locks,
+ provide_base_cb,
+ provide_props_cb,
+ get_copysrc_kind_cb,
+ cb_baton,
+ session->cancel_func, session->cancel_baton,
+ result_pool, scratch_pool));
+ }
+
+ /* Note: no need to remap the callback for Ev2. RA layers providing this
+ vtable entry should completely fill in commit_info. */
+
+ return svn_error_trace(session->vtable->get_commit_ev2(
+ editor,
+ session,
+ revprop_table,
+ commit_callback, commit_baton,
+ lock_tokens,
+ keep_locks,
+ provide_base_cb,
+ provide_props_cb,
+ get_copysrc_kind_cb,
+ cb_baton,
+ session->cancel_func, session->cancel_baton,
+ result_pool, scratch_pool));
+}
svn_error_t *
@@ -1268,7 +1436,7 @@ svn_ra_print_modules(svn_stringbuf_t *output,
built with SASL. */
line = apr_psprintf(iterpool, "* ra_%s : %s\n",
defn->ra_name,
- vtable->get_description());
+ vtable->get_description(iterpool));
svn_stringbuf_appendcstr(output, line);
for (schemes = vtable->get_schemes(iterpool); *schemes != NULL;
@@ -1292,11 +1460,20 @@ svn_ra_print_ra_libraries(svn_stringbuf_t **descriptions,
void *ra_baton,
apr_pool_t *pool)
{
- *descriptions = svn_stringbuf_create("", pool);
+ *descriptions = svn_stringbuf_create_empty(pool);
return svn_ra_print_modules(*descriptions, pool);
}
+svn_error_t *
+svn_ra__register_editor_shim_callbacks(svn_ra_session_t *session,
+ svn_delta_shim_callbacks_t *callbacks)
+{
+ SVN_ERR(session->vtable->register_editor_shim_callbacks(session, callbacks));
+ return SVN_NO_ERROR;
+}
+
+
/* Return the library version number. */
const svn_version_t *
svn_ra_version(void)
@@ -1328,7 +1505,7 @@ svn_ra_get_ra_library(svn_ra_plugin_t **library,
for (defn = ra_libraries; defn->ra_name != NULL; ++defn)
{
const char *scheme;
- if ((scheme = has_scheme_of(defn, url)))
+ if ((scheme = has_scheme_of(defn->schemes, url)))
{
svn_ra_init_func_t compat_initfunc = defn->compat_initfunc;
@@ -1344,7 +1521,7 @@ svn_ra_get_ra_library(svn_ra_plugin_t **library,
SVN_ERR(compat_initfunc(SVN_RA_ABI_VERSION, load_pool, ht));
- *library = apr_hash_get(ht, scheme, APR_HASH_KEY_STRING);
+ *library = svn_hash_gets(ht, scheme);
/* The library may support just a subset of the schemes listed,
so we have to check here too. */
diff --git a/subversion/libsvn_ra/ra_loader.h b/subversion/libsvn_ra/ra_loader.h
index ddb2581..227730a 100644
--- a/subversion/libsvn_ra/ra_loader.h
+++ b/subversion/libsvn_ra/ra_loader.h
@@ -32,6 +32,8 @@
#include "svn_ra.h"
+#include "private/svn_ra_private.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -43,7 +45,7 @@ typedef struct svn_ra__vtable_t {
/* Return a short description of the RA implementation, as a localized
* string. */
- const char *(*get_description)(void);
+ const char *(*get_description)(apr_pool_t *pool);
/* Return a list of actual URI schemes supported by this implementation.
* The returned array is NULL-terminated. */
@@ -56,7 +58,7 @@ typedef struct svn_ra__vtable_t {
time this is called. SESSION->priv may be set by this function. */
svn_error_t *(*open_session)(svn_ra_session_t *session,
const char **corrected_url,
- const char *repos_URL,
+ const char *session_URL,
const svn_ra_callbacks2_t *callbacks,
void *callback_baton,
apr_hash_t *config,
@@ -133,7 +135,7 @@ typedef struct svn_ra__vtable_t {
svn_mergeinfo_inheritance_t inherit,
svn_boolean_t include_merged_revisions,
apr_pool_t *pool);
- /* See svn_ra_do_update2(). */
+ /* See svn_ra_do_update3(). */
svn_error_t *(*do_update)(svn_ra_session_t *session,
const svn_ra_reporter3_t **reporter,
void **report_baton,
@@ -141,10 +143,12 @@ typedef struct svn_ra__vtable_t {
const char *update_target,
svn_depth_t depth,
svn_boolean_t send_copyfrom_args,
+ svn_boolean_t ignore_ancestry,
const svn_delta_editor_t *update_editor,
void *update_baton,
- apr_pool_t *pool);
- /* See svn_ra_do_switch2(). */
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+ /* See svn_ra_do_switch3(). */
svn_error_t *(*do_switch)(svn_ra_session_t *session,
const svn_ra_reporter3_t **reporter,
void **report_baton,
@@ -152,9 +156,12 @@ typedef struct svn_ra__vtable_t {
const char *switch_target,
svn_depth_t depth,
const char *switch_url,
+ svn_boolean_t send_copyfrom_args,
+ svn_boolean_t ignore_ancestry,
const svn_delta_editor_t *switch_editor,
void *switch_baton,
- apr_pool_t *pool);
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* See svn_ra_do_status2(). */
svn_error_t *(*do_status)(svn_ra_session_t *session,
const svn_ra_reporter3_t **reporter,
@@ -294,12 +301,56 @@ typedef struct svn_ra__vtable_t {
svn_revnum_t *revision_deleted,
apr_pool_t *pool);
+ /* See svn_ra__register_editor_shim_callbacks() */
+ svn_error_t *(*register_editor_shim_callbacks)(svn_ra_session_t *session,
+ svn_delta_shim_callbacks_t *callbacks);
+ /* See svn_ra_get_inherited_props(). */
+ svn_error_t *(*get_inherited_props)(svn_ra_session_t *session,
+ apr_array_header_t **iprops,
+ const char *path,
+ svn_revnum_t revision,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+ /* See svn_ra__get_commit_ev2() */
+ svn_error_t *(*get_commit_ev2)(
+ svn_editor_t **editor,
+ svn_ra_session_t *session,
+ apr_hash_t *revprop_table,
+ svn_commit_callback2_t callback,
+ void *callback_baton,
+ apr_hash_t *lock_tokens,
+ svn_boolean_t keep_locks,
+ svn_ra__provide_base_cb_t provide_base_cb,
+ svn_ra__provide_props_cb_t provide_props_cb,
+ svn_ra__get_copysrc_kind_cb_t get_copysrc_kind_cb,
+ void *cb_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+ /* See svn_ra__replay_range_ev2() */
+ svn_error_t *(*replay_range_ev2)(
+ svn_ra_session_t *session,
+ svn_revnum_t start_revision,
+ svn_revnum_t end_revision,
+ svn_revnum_t low_water_mark,
+ svn_boolean_t send_deltas,
+ svn_ra__replay_revstart_ev2_callback_t revstart_func,
+ svn_ra__replay_revfinish_ev2_callback_t revfinish_func,
+ void *replay_baton,
+ apr_pool_t *scratch_pool);
+
} svn_ra__vtable_t;
/* The RA session object. */
struct svn_ra_session_t {
const svn_ra__vtable_t *vtable;
+ /* Cancellation handlers consumers may want to use. */
+ svn_cancel_func_t cancel_func;
+ void *cancel_baton;
+
/* Pool used to manage this session. */
apr_pool_t *pool;
@@ -329,9 +380,6 @@ svn_error_t *svn_ra_local__init(const svn_version_t *loader_version,
svn_error_t *svn_ra_svn__init(const svn_version_t *loader_version,
const svn_ra__vtable_t **vtable,
apr_pool_t *pool);
-svn_error_t *svn_ra_neon__init(const svn_version_t *loader_version,
- const svn_ra__vtable_t **vtable,
- apr_pool_t *pool);
svn_error_t *svn_ra_serf__init(const svn_version_t *loader_version,
const svn_ra__vtable_t **vtable,
apr_pool_t *pool);
@@ -451,6 +499,62 @@ svn_ra__get_deleted_rev_from_log(svn_ra_session_t *session,
svn_revnum_t *revision_deleted,
apr_pool_t *pool);
+
+/**
+ * Fallback logic for svn_ra_get_inherited_props() when that API
+ * need to find PATH's inherited properties on a legacy server that
+ * doesn't have the SVN_RA_CAPABILITY_INHERITED_PROPS capability.
+ *
+ * All arguments are as per svn_ra_get_inherited_props().
+ */
+svn_error_t *
+svn_ra__get_inherited_props_walk(svn_ra_session_t *session,
+ const char *path,
+ svn_revnum_t revision,
+ apr_array_header_t **inherited_props,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/* Utility function to provide a shim between a returned Ev2 and an RA
+ provider's Ev1-based commit editor.
+
+ See svn_ra__get_commit_ev2() for parameter semantics. */
+svn_error_t *
+svn_ra__use_commit_shim(svn_editor_t **editor,
+ svn_ra_session_t *session,
+ apr_hash_t *revprop_table,
+ svn_commit_callback2_t callback,
+ void *callback_baton,
+ apr_hash_t *lock_tokens,
+ svn_boolean_t keep_locks,
+ svn_ra__provide_base_cb_t provide_base_cb,
+ svn_ra__provide_props_cb_t provide_props_cb,
+ svn_ra__get_copysrc_kind_cb_t get_copysrc_kind_cb,
+ void *cb_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/* Utility function to provide a shim between a returned Ev2 and an RA
+ provider's Ev1-based commit editor.
+
+ See svn_ra__replay_range_ev2() for parameter semantics. */
+svn_error_t *
+svn_ra__use_replay_range_shim(svn_ra_session_t *session,
+ svn_revnum_t start_revision,
+ svn_revnum_t end_revision,
+ svn_revnum_t low_water_mark,
+ svn_boolean_t send_deltas,
+ svn_ra__replay_revstart_ev2_callback_t revstart_func,
+ svn_ra__replay_revfinish_ev2_callback_t revfinish_func,
+ void *replay_baton,
+ svn_ra__provide_base_cb_t provide_base_cb,
+ svn_ra__provide_props_cb_t provide_props_cb,
+ void *cb_baton,
+ apr_pool_t *scratch_pool);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/subversion/libsvn_ra/util.c b/subversion/libsvn_ra/util.c
index 47e4865..d9a4520 100644
--- a/subversion/libsvn_ra/util.c
+++ b/subversion/libsvn_ra/util.c
@@ -38,6 +38,26 @@
#include "svn_private_config.h"
#include "private/svn_ra_private.h"
+static const char *
+get_path(const char *path_or_url,
+ svn_ra_session_t *ra_session,
+ apr_pool_t *pool)
+{
+ if (path_or_url == NULL)
+ {
+ svn_error_t *err = svn_ra_get_session_url(ra_session, &path_or_url,
+ pool);
+ if (err)
+ {
+ /* The SVN_ERR_UNSUPPORTED_FEATURE error in the caller is more
+ important, so dummy up the session's URL and chuck this error. */
+ svn_error_clear(err);
+ return _("<repository>");
+ }
+ }
+ return path_or_url;
+}
+
svn_error_t *
svn_ra__assert_mergeinfo_capable_server(svn_ra_session_t *ra_session,
const char *path_or_url,
@@ -48,18 +68,7 @@ svn_ra__assert_mergeinfo_capable_server(svn_ra_session_t *ra_session,
SVN_RA_CAPABILITY_MERGEINFO, pool));
if (! mergeinfo_capable)
{
- if (path_or_url == NULL)
- {
- svn_error_t *err = svn_ra_get_session_url(ra_session, &path_or_url,
- pool);
- if (err)
- {
- /* The SVN_ERR_UNSUPPORTED_FEATURE error is more important,
- so dummy up the session's URL and chuck this error. */
- svn_error_clear(err);
- path_or_url = "<repository>";
- }
- }
+ path_or_url = get_path(path_or_url, ra_session, pool);
return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
_("Retrieval of mergeinfo unsupported by '%s'"),
svn_path_is_url(path_or_url)
@@ -69,6 +78,35 @@ svn_ra__assert_mergeinfo_capable_server(svn_ra_session_t *ra_session,
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_ra__assert_capable_server(svn_ra_session_t *ra_session,
+ const char *capability,
+ const char *path_or_url,
+ apr_pool_t *pool)
+{
+ if (!strcmp(capability, SVN_RA_CAPABILITY_MERGEINFO))
+ return svn_ra__assert_mergeinfo_capable_server(ra_session, path_or_url,
+ pool);
+
+ else
+ {
+ svn_boolean_t has;
+ SVN_ERR(svn_ra_has_capability(ra_session, &has, capability, pool));
+ if (! has)
+ {
+ path_or_url = get_path(path_or_url, ra_session, pool);
+ return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+ _("The '%s' feature is not supported by '%s'"),
+ capability,
+ svn_path_is_url(path_or_url)
+ ? path_or_url
+ : svn_dirent_local_style(path_or_url,
+ pool));
+ }
+ }
+ return SVN_NO_ERROR;
+}
+
/* Does ERR mean "the current value of the revprop isn't equal to
the *OLD_VALUE_P you gave me"?
*/
diff --git a/subversion/libsvn_ra/wrapper_template.h b/subversion/libsvn_ra/wrapper_template.h
index e5426dc..cee3fb3 100644
--- a/subversion/libsvn_ra/wrapper_template.h
+++ b/subversion/libsvn_ra/wrapper_template.h
@@ -291,8 +291,10 @@ static svn_error_t *compat_do_update(void *session_baton,
SVN_ERR(VTBL.do_update(session_baton, &reporter3, &baton3,
revision_to_update_to, update_target, depth,
- FALSE, /* no copyfrom args */
- editor, update_baton, pool));
+ FALSE /* send_copyfrom_args */,
+ FALSE /* ignore_ancestry */,
+ editor, update_baton,
+ pool, pool));
compat_wrap_reporter(reporter, report_baton, reporter3, baton3, pool);
return SVN_NO_ERROR;
@@ -315,7 +317,11 @@ static svn_error_t *compat_do_switch(void *session_baton,
SVN_ERR(VTBL.do_switch(session_baton, &reporter3, &baton3,
revision_to_switch_to, switch_target, depth,
- switch_url, editor, switch_baton, pool));
+ switch_url,
+ FALSE /* send_copyfrom_args */,
+ TRUE /* ignore_ancestry */,
+ editor, switch_baton,
+ pool /* result_pool */, pool /* scratch_pool */));
compat_wrap_reporter(reporter, report_baton, reporter3, baton3, pool);