]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/subversion/subversion/libsvn_ra/wrapper_template.h
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / subversion / subversion / libsvn_ra / wrapper_template.h
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
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
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
22  */
23
24 #include <apr_pools.h>
25 #include <apr_hash.h>
26 #include <apr_time.h>
27
28 #include "svn_types.h"
29 #include "svn_string.h"
30 #include "svn_props.h"
31 #include "svn_compat.h"
32
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.
37  *
38  * A file in the RA library includes this file, providing the
39  * following macros before inclusion:
40  *
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.
46  */
47
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
53
54
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)
61 {
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).
68    *
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));
77
78   svn_ra_session_t *sess = apr_pcalloc(sesspool, sizeof(*sess));
79   const char *session_url;
80
81   sess->vtable = &VTBL;
82   sess->pool = sesspool;
83
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;
92
93   SVN_ERR(VTBL.open_session(sess, &session_url, repos_URL,
94                             callbacks2, callback_baton, config, sesspool));
95
96   if (strcmp(repos_URL, session_url) != 0)
97     {
98       svn_pool_destroy(sesspool);
99       return svn_error_createf(SVN_ERR_RA_SESSION_URL_MISMATCH, NULL,
100                                _("Session URL '%s' does not match requested "
101                                  " URL '%s', and redirection was disallowed."),
102                                session_url, repos_URL);
103     }
104
105   *session_baton = sess;
106   return SVN_NO_ERROR;
107 }
108
109 static svn_error_t *compat_get_latest_revnum(void *session_baton,
110                                              svn_revnum_t *latest_revnum,
111                                              apr_pool_t *pool)
112 {
113   return VTBL.get_latest_revnum(session_baton, latest_revnum, pool);
114 }
115
116 static svn_error_t *compat_get_dated_revision(void *session_baton,
117                                               svn_revnum_t *revision,
118                                               apr_time_t tm,
119                                               apr_pool_t *pool)
120 {
121   return VTBL.get_dated_revision(session_baton, revision, tm, pool);
122 }
123
124 static svn_error_t *compat_change_rev_prop(void *session_baton,
125                                            svn_revnum_t rev,
126                                            const char *propname,
127                                            const svn_string_t *value,
128                                            apr_pool_t *pool)
129 {
130   return VTBL.change_rev_prop(session_baton, rev, propname, NULL, value, pool);
131 }
132
133 static svn_error_t *compat_rev_proplist(void *session_baton,
134                                         svn_revnum_t rev,
135                                         apr_hash_t **props,
136                                         apr_pool_t *pool)
137 {
138   return VTBL.rev_proplist(session_baton, rev, props, pool);
139 }
140
141 static svn_error_t *compat_rev_prop(void *session_baton,
142                                     svn_revnum_t rev,
143                                     const char *propname,
144                                     svn_string_t **value,
145                                     apr_pool_t *pool)
146 {
147   return VTBL.rev_prop(session_baton, rev, propname, value, pool);
148 }
149
150 static svn_error_t *compat_get_commit_editor(void *session_baton,
151                                              const svn_delta_editor_t
152                                              **editor,
153                                              void **edit_baton,
154                                              const char *log_msg,
155                                              svn_commit_callback_t callback,
156                                              void *callback_baton,
157                                              apr_pool_t *pool)
158 {
159   svn_commit_callback2_t callback2;
160   void *callback2_baton;
161   apr_hash_t *revprop_table = apr_hash_make(pool);
162
163   svn_compat_wrap_commit_callback(&callback2, &callback2_baton,
164                                   callback, callback_baton,
165                                   pool);
166   apr_hash_set(revprop_table, SVN_PROP_REVISION_LOG, APR_HASH_KEY_STRING,
167                svn_string_create(log_msg, pool));
168   return VTBL.get_commit_editor(session_baton, editor, edit_baton,
169                                 revprop_table, callback2, callback2_baton,
170                                 NULL, TRUE, pool);
171 }
172
173 static svn_error_t *compat_get_file(void *session_baton,
174                                     const char *path,
175                                     svn_revnum_t revision,
176                                     svn_stream_t *stream,
177                                     svn_revnum_t *fetched_rev,
178                                     apr_hash_t **props,
179                                     apr_pool_t *pool)
180 {
181   return VTBL.get_file(session_baton, path, revision, stream, fetched_rev,
182                        props, pool);
183 }
184
185 static svn_error_t *compat_get_dir(void *session_baton,
186                                    const char *path,
187                                    svn_revnum_t revision,
188                                    apr_hash_t **dirents,
189                                    svn_revnum_t *fetched_rev,
190                                    apr_hash_t **props,
191                                    apr_pool_t *pool)
192 {
193   return VTBL.get_dir(session_baton, dirents, fetched_rev, props,
194                       path, revision, SVN_DIRENT_ALL, pool);
195 }
196
197 /** Reporter compat code. **/
198
199 struct compat_report_baton {
200   const svn_ra_reporter3_t *reporter;
201   void *baton;
202 };
203
204 static svn_error_t *compat_set_path(void *report_baton,
205                                     const char *path,
206                                     svn_revnum_t revision,
207                                     svn_boolean_t start_empty,
208                                     apr_pool_t *pool)
209 {
210   struct compat_report_baton *crb = report_baton;
211
212   return crb->reporter->set_path(crb->baton, path, revision,
213                                  svn_depth_infinity, start_empty,
214                                  NULL, pool);
215 }
216
217 static svn_error_t *compat_delete_path(void *report_baton,
218                                        const char *path,
219                                        apr_pool_t *pool)
220 {
221   struct compat_report_baton *crb = report_baton;
222
223   return crb->reporter->delete_path(crb->baton, path, pool);
224 }
225
226 static svn_error_t *compat_link_path(void *report_baton,
227                                      const char *path,
228                                      const char *url,
229                                      svn_revnum_t revision,
230                                      svn_boolean_t start_empty,
231                                      apr_pool_t *pool)
232 {
233   struct compat_report_baton *crb = report_baton;
234
235   return crb->reporter->link_path(crb->baton, path, url, revision,
236                                   svn_depth_infinity, start_empty,
237                                   NULL, pool);
238 }
239
240 static svn_error_t *compat_finish_report(void *report_baton,
241                                          apr_pool_t *pool)
242 {
243   struct compat_report_baton *crb = report_baton;
244
245   return crb->reporter->finish_report(crb->baton, pool);
246 }
247
248 static svn_error_t *compat_abort_report(void *report_baton,
249                                         apr_pool_t *pool)
250 {
251   struct compat_report_baton *crb = report_baton;
252
253   return crb->reporter->abort_report(crb->baton, pool);
254 }
255
256 static const svn_ra_reporter_t compat_reporter = {
257   compat_set_path,
258   compat_delete_path,
259   compat_link_path,
260   compat_finish_report,
261   compat_abort_report
262 };
263
264 static void compat_wrap_reporter(const svn_ra_reporter_t **reporter,
265                                  void **baton,
266                                  const svn_ra_reporter3_t *wrapped,
267                                  void *wrapped_baton,
268                                  apr_pool_t *pool)
269 {
270   struct compat_report_baton *crb = apr_palloc(pool, sizeof(*crb));
271   crb->reporter = wrapped;
272   crb->baton = wrapped_baton;
273
274   *reporter = &compat_reporter;
275   *baton = crb;
276 }
277
278 static svn_error_t *compat_do_update(void *session_baton,
279                                      const svn_ra_reporter_t **reporter,
280                                      void **report_baton,
281                                      svn_revnum_t revision_to_update_to,
282                                      const char *update_target,
283                                      svn_boolean_t recurse,
284                                      const svn_delta_editor_t *editor,
285                                      void *update_baton,
286                                      apr_pool_t *pool)
287 {
288   const svn_ra_reporter3_t *reporter3;
289   void *baton3;
290   svn_depth_t depth = SVN_DEPTH_INFINITY_OR_FILES(recurse);
291
292   SVN_ERR(VTBL.do_update(session_baton, &reporter3, &baton3,
293                          revision_to_update_to, update_target, depth,
294                          FALSE /* send_copyfrom_args */,
295                          FALSE /* ignore_ancestry */,
296                          editor, update_baton,
297                          pool, pool));
298   compat_wrap_reporter(reporter, report_baton, reporter3, baton3, pool);
299
300   return SVN_NO_ERROR;
301 }
302
303 static svn_error_t *compat_do_switch(void *session_baton,
304                                      const svn_ra_reporter_t **reporter,
305                                      void **report_baton,
306                                      svn_revnum_t revision_to_switch_to,
307                                      const char *switch_target,
308                                      svn_boolean_t recurse,
309                                      const char *switch_url,
310                                      const svn_delta_editor_t *editor,
311                                      void *switch_baton,
312                                      apr_pool_t *pool)
313 {
314   const svn_ra_reporter3_t *reporter3;
315   void *baton3;
316   svn_depth_t depth = SVN_DEPTH_INFINITY_OR_FILES(recurse);
317
318   SVN_ERR(VTBL.do_switch(session_baton, &reporter3, &baton3,
319                          revision_to_switch_to, switch_target, depth,
320                          switch_url,
321                          FALSE /* send_copyfrom_args */,
322                          TRUE /* ignore_ancestry */,
323                          editor, switch_baton,
324                          pool /* result_pool */, pool /* scratch_pool */));
325
326   compat_wrap_reporter(reporter, report_baton, reporter3, baton3, pool);
327
328   return SVN_NO_ERROR;
329 }
330
331 static svn_error_t *compat_do_status(void *session_baton,
332                                      const svn_ra_reporter_t **reporter,
333                                      void **report_baton,
334                                      const char *status_target,
335                                      svn_revnum_t revision,
336                                      svn_boolean_t recurse,
337                                      const svn_delta_editor_t *editor,
338                                      void *status_baton,
339                                      apr_pool_t *pool)
340 {
341   const svn_ra_reporter3_t *reporter3;
342   void *baton3;
343   svn_depth_t depth = SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse);
344
345   SVN_ERR(VTBL.do_status(session_baton, &reporter3, &baton3, status_target,
346                          revision, depth, editor, status_baton, pool));
347
348   compat_wrap_reporter(reporter, report_baton, reporter3, baton3, pool);
349
350   return SVN_NO_ERROR;
351 }
352
353 static svn_error_t *compat_do_diff(void *session_baton,
354                                    const svn_ra_reporter_t **reporter,
355                                    void **report_baton,
356                                    svn_revnum_t revision,
357                                    const char *diff_target,
358                                    svn_boolean_t recurse,
359                                    svn_boolean_t ignore_ancestry,
360                                    const char *versus_url,
361                                    const svn_delta_editor_t *diff_editor,
362                                    void *diff_baton,
363                                    apr_pool_t *pool)
364 {
365   const svn_ra_reporter3_t *reporter3;
366   void *baton3;
367   svn_depth_t depth = SVN_DEPTH_INFINITY_OR_FILES(recurse);
368
369   SVN_ERR(VTBL.do_diff(session_baton, &reporter3, &baton3, revision,
370                        diff_target, depth, ignore_ancestry, TRUE,
371                        versus_url, diff_editor, diff_baton, pool));
372
373   compat_wrap_reporter(reporter, report_baton, reporter3, baton3, pool);
374
375   return SVN_NO_ERROR;
376 }
377
378 static svn_error_t *compat_get_log(void *session_baton,
379                                    const apr_array_header_t *paths,
380                                    svn_revnum_t start,
381                                    svn_revnum_t end,
382                                    svn_boolean_t discover_changed_paths,
383                                    svn_boolean_t strict_node_history,
384                                    svn_log_message_receiver_t receiver,
385                                    void *receiver_baton,
386                                    apr_pool_t *pool)
387 {
388   svn_log_entry_receiver_t receiver2;
389   void *receiver2_baton;
390
391   svn_compat_wrap_log_receiver(&receiver2, &receiver2_baton,
392                                receiver, receiver_baton,
393                                pool);
394
395   return VTBL.get_log(session_baton, paths, start, end, 0, /* limit */
396                       discover_changed_paths, strict_node_history,
397                       FALSE, /* include_merged_revisions */
398                       svn_compat_log_revprops_in(pool), /* revprops */
399                       receiver2, receiver2_baton, pool);
400 }
401
402 static svn_error_t *compat_check_path(void *session_baton,
403                                       const char *path,
404                                       svn_revnum_t revision,
405                                       svn_node_kind_t *kind,
406                                       apr_pool_t *pool)
407 {
408   return VTBL.check_path(session_baton, path, revision, kind, pool);
409 }
410
411 static svn_error_t *compat_get_uuid(void *session_baton,
412                                     const char **uuid,
413                                     apr_pool_t *pool)
414 {
415   return VTBL.get_uuid(session_baton, uuid, pool);
416 }
417
418 static svn_error_t *compat_get_repos_root(void *session_baton,
419                                           const char **url,
420                                           apr_pool_t *pool)
421 {
422   return VTBL.get_repos_root(session_baton, url, pool);
423 }
424
425 static svn_error_t *compat_get_locations(void *session_baton,
426                                          apr_hash_t **locations,
427                                          const char *path,
428                                          svn_revnum_t peg_revision,
429                                          apr_array_header_t *location_revs,
430                                          apr_pool_t *pool)
431 {
432   return VTBL.get_locations(session_baton, locations, path, peg_revision,
433                             location_revs, pool);
434 }
435
436 static svn_error_t *compat_get_file_revs(void *session_baton,
437                                          const char *path,
438                                          svn_revnum_t start,
439                                          svn_revnum_t end,
440                                          svn_ra_file_rev_handler_t handler,
441                                          void *handler_baton,
442                                          apr_pool_t *pool)
443 {
444   svn_file_rev_handler_t handler2;
445   void *handler2_baton;
446
447   svn_compat_wrap_file_rev_handler(&handler2, &handler2_baton,
448                                    handler, handler_baton,
449                                    pool);
450
451   return VTBL.get_file_revs(session_baton, path, start, end,
452                             FALSE, /* include merged revisions */
453                             handler2, handler2_baton, pool);
454 }
455
456 static const svn_version_t *compat_get_version(void)
457 {
458   return VTBL.get_version();
459 }
460
461
462 static const svn_ra_plugin_t compat_plugin = {
463   NAME,
464   DESCRIPTION,
465   compat_open,
466   compat_get_latest_revnum,
467   compat_get_dated_revision,
468   compat_change_rev_prop,
469   compat_rev_proplist,
470   compat_rev_prop,
471   compat_get_commit_editor,
472   compat_get_file,
473   compat_get_dir,
474   compat_do_update,
475   compat_do_switch,
476   compat_do_status,
477   compat_do_diff,
478   compat_get_log,
479   compat_check_path,
480   compat_get_uuid,
481   compat_get_repos_root,
482   compat_get_locations,
483   compat_get_file_revs,
484   compat_get_version
485 };
486
487 svn_error_t *
488 COMPAT_INITFUNC(int abi_version,
489                 apr_pool_t *pool,
490                 apr_hash_t *hash)
491 {
492   const svn_ra__vtable_t *vtable;
493   const char * const * schemes;
494
495   if (abi_version < 1
496       || abi_version > SVN_RA_ABI_VERSION)
497     return svn_error_createf(SVN_ERR_RA_UNSUPPORTED_ABI_VERSION, NULL,
498                              _("Unsupported RA plugin ABI version (%d) "
499                                "for %s"), abi_version, NAME);
500
501   /* We call the new init function so it can check library dependencies or
502      do other initialization things.  We fake the loader version, since we
503      rely on the ABI version check instead. */
504   SVN_ERR(INITFUNC(VTBL.get_version(), &vtable, pool));
505
506   schemes = VTBL.get_schemes(pool);
507
508   for (; *schemes != NULL; ++schemes)
509     apr_hash_set(hash, *schemes, APR_HASH_KEY_STRING, &compat_plugin);
510
511   return SVN_NO_ERROR;
512 }