Win32: fix an incorrect error status being propagated to the caller in case
[svn/apache.git] / subversion / libsvn_ra / wrapper_template.h
blob0585deda87db53781d60cd5be5a972b8a52b336a
1 /**
2 * @copyright
3 * ====================================================================
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 * ====================================================================
21 * @endcopyright
24 #include <apr_pools.h>
25 #include <apr_hash.h>
26 #include <apr_time.h>
28 #include "svn_types.h"
29 #include "svn_string.h"
30 #include "svn_props.h"
31 #include "svn_compat.h"
33 /* This file is a template for a compatibility wrapper for an RA library.
34 * It contains an svn_ra_plugin_t and wrappers for all of its functions,
35 * implemented in terms of svn_ra__vtable_t functions. It also contains
36 * the implementations of an svn_ra_FOO_init for the FOO RA library.
38 * A file in the RA library includes this file, providing the
39 * following macros before inclusion:
41 * NAME The library name, e.g. "ra_local".
42 * DESCRIPTION The short library description as a string constant.
43 * VTBL The name of an svn_ra_vtable_t object for the library.
44 * INITFUNC The init function for the library, e.g. svn_ra_local__init.
45 * COMPAT_INITFUNC The compatibility init function, e.g. svn_ra_local_init.
48 /* Check that all our "arguments" are defined. */
49 #if ! defined(NAME) || ! defined(DESCRIPTION) || ! defined(VTBL) \
50 || ! defined(INITFUNC) || ! defined(COMPAT_INITFUNC)
51 #error Missing define for RA compatibility wrapper.
52 #endif
55 static svn_error_t *compat_open(void **session_baton,
56 const char *repos_URL,
57 const svn_ra_callbacks_t *callbacks,
58 void *callback_baton,
59 apr_hash_t *config,
60 apr_pool_t *pool)
62 /* Here, we should be calling svn_ra_create_callbacks to initialize
63 * the svn_ra_callbacks2_t structure. However, doing that
64 * introduces a circular dependancy between libsvn_ra and
65 * libsvn_ra_{local,neon,serf,svn}, which include
66 * wrapper_template.h. In turn, circular dependancies break the
67 * build on win32 (and possibly other systems).
69 * In order to avoid this happening at all, the code of
70 * svn_ra_create_callbacks is duplicated here. This is evil, but
71 * the alternative (creating a new ra_util library) would be massive
72 * overkill for the time being. Just be sure to keep the following
73 * line and the code of svn_ra_create_callbacks in sync. */
74 apr_pool_t *sesspool = svn_pool_create(pool);
75 svn_ra_callbacks2_t *callbacks2 = apr_pcalloc(sesspool,
76 sizeof(*callbacks2));
78 svn_ra_session_t *sess = apr_pcalloc(sesspool, sizeof(*sess));
79 const char *session_url;
81 sess->vtable = &VTBL;
82 sess->pool = sesspool;
84 callbacks2->open_tmp_file = callbacks->open_tmp_file;
85 callbacks2->auth_baton = callbacks->auth_baton;
86 callbacks2->get_wc_prop = callbacks->get_wc_prop;
87 callbacks2->set_wc_prop = callbacks->set_wc_prop;
88 callbacks2->push_wc_prop = callbacks->push_wc_prop;
89 callbacks2->invalidate_wc_props = callbacks->invalidate_wc_props;
90 callbacks2->progress_func = NULL;
91 callbacks2->progress_baton = NULL;
93 SVN_ERR(VTBL.open_session(sess, &session_url, repos_URL,
94 callbacks2, callback_baton,
95 callbacks ? callbacks->auth_baton : NULL,
96 config, sesspool, sesspool));
98 if (strcmp(repos_URL, session_url) != 0)
100 svn_pool_destroy(sesspool);
101 return svn_error_createf(SVN_ERR_RA_SESSION_URL_MISMATCH, NULL,
102 _("Session URL '%s' does not match requested "
103 " URL '%s', and redirection was disallowed."),
104 session_url, repos_URL);
107 *session_baton = sess;
108 return SVN_NO_ERROR;
111 static svn_error_t *compat_get_latest_revnum(void *session_baton,
112 svn_revnum_t *latest_revnum,
113 apr_pool_t *pool)
115 return VTBL.get_latest_revnum(session_baton, latest_revnum, pool);
118 static svn_error_t *compat_get_dated_revision(void *session_baton,
119 svn_revnum_t *revision,
120 apr_time_t tm,
121 apr_pool_t *pool)
123 return VTBL.get_dated_revision(session_baton, revision, tm, pool);
126 static svn_error_t *compat_change_rev_prop(void *session_baton,
127 svn_revnum_t rev,
128 const char *propname,
129 const svn_string_t *value,
130 apr_pool_t *pool)
132 return VTBL.change_rev_prop(session_baton, rev, propname, NULL, value, pool);
135 static svn_error_t *compat_rev_proplist(void *session_baton,
136 svn_revnum_t rev,
137 apr_hash_t **props,
138 apr_pool_t *pool)
140 return VTBL.rev_proplist(session_baton, rev, props, pool);
143 static svn_error_t *compat_rev_prop(void *session_baton,
144 svn_revnum_t rev,
145 const char *propname,
146 svn_string_t **value,
147 apr_pool_t *pool)
149 return VTBL.rev_prop(session_baton, rev, propname, value, pool);
152 static svn_error_t *compat_get_commit_editor(void *session_baton,
153 const svn_delta_editor_t
154 **editor,
155 void **edit_baton,
156 const char *log_msg,
157 svn_commit_callback_t callback,
158 void *callback_baton,
159 apr_pool_t *pool)
161 svn_commit_callback2_t callback2;
162 void *callback2_baton;
163 apr_hash_t *revprop_table = apr_hash_make(pool);
165 svn_compat_wrap_commit_callback(&callback2, &callback2_baton,
166 callback, callback_baton,
167 pool);
168 apr_hash_set(revprop_table, SVN_PROP_REVISION_LOG, APR_HASH_KEY_STRING,
169 svn_string_create(log_msg, pool));
170 return VTBL.get_commit_editor(session_baton, editor, edit_baton,
171 revprop_table, callback2, callback2_baton,
172 NULL, TRUE, pool);
175 static svn_error_t *compat_get_file(void *session_baton,
176 const char *path,
177 svn_revnum_t revision,
178 svn_stream_t *stream,
179 svn_revnum_t *fetched_rev,
180 apr_hash_t **props,
181 apr_pool_t *pool)
183 return VTBL.get_file(session_baton, path, revision, stream, fetched_rev,
184 props, pool);
187 static svn_error_t *compat_get_dir(void *session_baton,
188 const char *path,
189 svn_revnum_t revision,
190 apr_hash_t **dirents,
191 svn_revnum_t *fetched_rev,
192 apr_hash_t **props,
193 apr_pool_t *pool)
195 return VTBL.get_dir(session_baton, dirents, fetched_rev, props,
196 path, revision, SVN_DIRENT_ALL, pool);
199 /** Reporter compat code. **/
201 struct compat_report_baton {
202 const svn_ra_reporter3_t *reporter;
203 void *baton;
206 static svn_error_t *compat_set_path(void *report_baton,
207 const char *path,
208 svn_revnum_t revision,
209 svn_boolean_t start_empty,
210 apr_pool_t *pool)
212 struct compat_report_baton *crb = report_baton;
214 return crb->reporter->set_path(crb->baton, path, revision,
215 svn_depth_infinity, start_empty,
216 NULL, pool);
219 static svn_error_t *compat_delete_path(void *report_baton,
220 const char *path,
221 apr_pool_t *pool)
223 struct compat_report_baton *crb = report_baton;
225 return crb->reporter->delete_path(crb->baton, path, pool);
228 static svn_error_t *compat_link_path(void *report_baton,
229 const char *path,
230 const char *url,
231 svn_revnum_t revision,
232 svn_boolean_t start_empty,
233 apr_pool_t *pool)
235 struct compat_report_baton *crb = report_baton;
237 return crb->reporter->link_path(crb->baton, path, url, revision,
238 svn_depth_infinity, start_empty,
239 NULL, pool);
242 static svn_error_t *compat_finish_report(void *report_baton,
243 apr_pool_t *pool)
245 struct compat_report_baton *crb = report_baton;
247 return crb->reporter->finish_report(crb->baton, pool);
250 static svn_error_t *compat_abort_report(void *report_baton,
251 apr_pool_t *pool)
253 struct compat_report_baton *crb = report_baton;
255 return crb->reporter->abort_report(crb->baton, pool);
258 static const svn_ra_reporter_t compat_reporter = {
259 compat_set_path,
260 compat_delete_path,
261 compat_link_path,
262 compat_finish_report,
263 compat_abort_report
266 static void compat_wrap_reporter(const svn_ra_reporter_t **reporter,
267 void **baton,
268 const svn_ra_reporter3_t *wrapped,
269 void *wrapped_baton,
270 apr_pool_t *pool)
272 struct compat_report_baton *crb = apr_palloc(pool, sizeof(*crb));
273 crb->reporter = wrapped;
274 crb->baton = wrapped_baton;
276 *reporter = &compat_reporter;
277 *baton = crb;
280 static svn_error_t *compat_do_update(void *session_baton,
281 const svn_ra_reporter_t **reporter,
282 void **report_baton,
283 svn_revnum_t revision_to_update_to,
284 const char *update_target,
285 svn_boolean_t recurse,
286 const svn_delta_editor_t *editor,
287 void *update_baton,
288 apr_pool_t *pool)
290 const svn_ra_reporter3_t *reporter3;
291 void *baton3;
292 svn_depth_t depth = SVN_DEPTH_INFINITY_OR_FILES(recurse);
294 SVN_ERR(VTBL.do_update(session_baton, &reporter3, &baton3,
295 revision_to_update_to, update_target, depth,
296 FALSE /* send_copyfrom_args */,
297 FALSE /* ignore_ancestry */,
298 editor, update_baton,
299 pool, pool));
300 compat_wrap_reporter(reporter, report_baton, reporter3, baton3, pool);
302 return SVN_NO_ERROR;
305 static svn_error_t *compat_do_switch(void *session_baton,
306 const svn_ra_reporter_t **reporter,
307 void **report_baton,
308 svn_revnum_t revision_to_switch_to,
309 const char *switch_target,
310 svn_boolean_t recurse,
311 const char *switch_url,
312 const svn_delta_editor_t *editor,
313 void *switch_baton,
314 apr_pool_t *pool)
316 const svn_ra_reporter3_t *reporter3;
317 void *baton3;
318 svn_depth_t depth = SVN_DEPTH_INFINITY_OR_FILES(recurse);
320 SVN_ERR(VTBL.do_switch(session_baton, &reporter3, &baton3,
321 revision_to_switch_to, switch_target, depth,
322 switch_url,
323 FALSE /* send_copyfrom_args */,
324 TRUE /* ignore_ancestry */,
325 editor, switch_baton,
326 pool /* result_pool */, pool /* scratch_pool */));
328 compat_wrap_reporter(reporter, report_baton, reporter3, baton3, pool);
330 return SVN_NO_ERROR;
333 static svn_error_t *compat_do_status(void *session_baton,
334 const svn_ra_reporter_t **reporter,
335 void **report_baton,
336 const char *status_target,
337 svn_revnum_t revision,
338 svn_boolean_t recurse,
339 const svn_delta_editor_t *editor,
340 void *status_baton,
341 apr_pool_t *pool)
343 const svn_ra_reporter3_t *reporter3;
344 void *baton3;
345 svn_depth_t depth = SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse);
347 SVN_ERR(VTBL.do_status(session_baton, &reporter3, &baton3, status_target,
348 revision, depth, editor, status_baton, pool));
350 compat_wrap_reporter(reporter, report_baton, reporter3, baton3, pool);
352 return SVN_NO_ERROR;
355 static svn_error_t *compat_do_diff(void *session_baton,
356 const svn_ra_reporter_t **reporter,
357 void **report_baton,
358 svn_revnum_t revision,
359 const char *diff_target,
360 svn_boolean_t recurse,
361 svn_boolean_t ignore_ancestry,
362 const char *versus_url,
363 const svn_delta_editor_t *diff_editor,
364 void *diff_baton,
365 apr_pool_t *pool)
367 const svn_ra_reporter3_t *reporter3;
368 void *baton3;
369 svn_depth_t depth = SVN_DEPTH_INFINITY_OR_FILES(recurse);
371 SVN_ERR(VTBL.do_diff(session_baton, &reporter3, &baton3, revision,
372 diff_target, depth, ignore_ancestry, TRUE,
373 versus_url, diff_editor, diff_baton, pool));
375 compat_wrap_reporter(reporter, report_baton, reporter3, baton3, pool);
377 return SVN_NO_ERROR;
380 static svn_error_t *compat_get_log(void *session_baton,
381 const apr_array_header_t *paths,
382 svn_revnum_t start,
383 svn_revnum_t end,
384 svn_boolean_t discover_changed_paths,
385 svn_boolean_t strict_node_history,
386 svn_log_message_receiver_t receiver,
387 void *receiver_baton,
388 apr_pool_t *pool)
390 svn_log_entry_receiver_t receiver2;
391 void *receiver2_baton;
393 svn_compat_wrap_log_receiver(&receiver2, &receiver2_baton,
394 receiver, receiver_baton,
395 pool);
397 return VTBL.get_log(session_baton, paths, start, end, 0, /* limit */
398 discover_changed_paths, strict_node_history,
399 FALSE, /* include_merged_revisions */
400 svn_compat_log_revprops_in(pool), /* revprops */
401 receiver2, receiver2_baton, pool);
404 static svn_error_t *compat_check_path(void *session_baton,
405 const char *path,
406 svn_revnum_t revision,
407 svn_node_kind_t *kind,
408 apr_pool_t *pool)
410 return VTBL.check_path(session_baton, path, revision, kind, pool);
413 static svn_error_t *compat_get_uuid(void *session_baton,
414 const char **uuid,
415 apr_pool_t *pool)
417 return VTBL.get_uuid(session_baton, uuid, pool);
420 static svn_error_t *compat_get_repos_root(void *session_baton,
421 const char **url,
422 apr_pool_t *pool)
424 return VTBL.get_repos_root(session_baton, url, pool);
427 static svn_error_t *compat_get_locations(void *session_baton,
428 apr_hash_t **locations,
429 const char *path,
430 svn_revnum_t peg_revision,
431 apr_array_header_t *location_revs,
432 apr_pool_t *pool)
434 return VTBL.get_locations(session_baton, locations, path, peg_revision,
435 location_revs, pool);
438 static svn_error_t *compat_get_file_revs(void *session_baton,
439 const char *path,
440 svn_revnum_t start,
441 svn_revnum_t end,
442 svn_ra_file_rev_handler_t handler,
443 void *handler_baton,
444 apr_pool_t *pool)
446 svn_file_rev_handler_t handler2;
447 void *handler2_baton;
449 svn_compat_wrap_file_rev_handler(&handler2, &handler2_baton,
450 handler, handler_baton,
451 pool);
453 return VTBL.get_file_revs(session_baton, path, start, end,
454 FALSE, /* include merged revisions */
455 handler2, handler2_baton, pool);
458 static const svn_version_t *compat_get_version(void)
460 return VTBL.get_version();
464 static const svn_ra_plugin_t compat_plugin = {
465 NAME,
466 DESCRIPTION,
467 compat_open,
468 compat_get_latest_revnum,
469 compat_get_dated_revision,
470 compat_change_rev_prop,
471 compat_rev_proplist,
472 compat_rev_prop,
473 compat_get_commit_editor,
474 compat_get_file,
475 compat_get_dir,
476 compat_do_update,
477 compat_do_switch,
478 compat_do_status,
479 compat_do_diff,
480 compat_get_log,
481 compat_check_path,
482 compat_get_uuid,
483 compat_get_repos_root,
484 compat_get_locations,
485 compat_get_file_revs,
486 compat_get_version
489 svn_error_t *
490 COMPAT_INITFUNC(int abi_version,
491 apr_pool_t *pool,
492 apr_hash_t *hash)
494 const svn_ra__vtable_t *vtable;
495 const char * const * schemes;
497 if (abi_version < 1
498 || abi_version > SVN_RA_ABI_VERSION)
499 return svn_error_createf(SVN_ERR_RA_UNSUPPORTED_ABI_VERSION, NULL,
500 _("Unsupported RA plugin ABI version (%d) "
501 "for %s"), abi_version, NAME);
503 /* We call the new init function so it can check library dependencies or
504 do other initialization things. We fake the loader version, since we
505 rely on the ABI version check instead. */
506 SVN_ERR(INITFUNC(VTBL.get_version(), &vtable, pool));
508 schemes = VTBL.get_schemes(pool);
510 for (; *schemes != NULL; ++schemes)
511 apr_hash_set(hash, *schemes, APR_HASH_KEY_STRING, &compat_plugin);
513 return SVN_NO_ERROR;