]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/subversion/subversion/libsvn_ra/wrapper_template.h
MFC r275385 (by bapt):
[FreeBSD/stable/10.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,
95                             callbacks ? callbacks->auth_baton : NULL,
96                             config, sesspool, sesspool));
97
98   if (strcmp(repos_URL, session_url) != 0)
99     {
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);
105     }
106
107   *session_baton = sess;
108   return SVN_NO_ERROR;
109 }
110
111 static svn_error_t *compat_get_latest_revnum(void *session_baton,
112                                              svn_revnum_t *latest_revnum,
113                                              apr_pool_t *pool)
114 {
115   return VTBL.get_latest_revnum(session_baton, latest_revnum, pool);
116 }
117
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)
122 {
123   return VTBL.get_dated_revision(session_baton, revision, tm, pool);
124 }
125
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)
131 {
132   return VTBL.change_rev_prop(session_baton, rev, propname, NULL, value, pool);
133 }
134
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)
139 {
140   return VTBL.rev_proplist(session_baton, rev, props, pool);
141 }
142
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)
148 {
149   return VTBL.rev_prop(session_baton, rev, propname, value, pool);
150 }
151
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)
160 {
161   svn_commit_callback2_t callback2;
162   void *callback2_baton;
163   apr_hash_t *revprop_table = apr_hash_make(pool);
164
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);
173 }
174
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)
182 {
183   return VTBL.get_file(session_baton, path, revision, stream, fetched_rev,
184                        props, pool);
185 }
186
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)
194 {
195   return VTBL.get_dir(session_baton, dirents, fetched_rev, props,
196                       path, revision, SVN_DIRENT_ALL, pool);
197 }
198
199 /** Reporter compat code. **/
200
201 struct compat_report_baton {
202   const svn_ra_reporter3_t *reporter;
203   void *baton;
204 };
205
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)
211 {
212   struct compat_report_baton *crb = report_baton;
213
214   return crb->reporter->set_path(crb->baton, path, revision,
215                                  svn_depth_infinity, start_empty,
216                                  NULL, pool);
217 }
218
219 static svn_error_t *compat_delete_path(void *report_baton,
220                                        const char *path,
221                                        apr_pool_t *pool)
222 {
223   struct compat_report_baton *crb = report_baton;
224
225   return crb->reporter->delete_path(crb->baton, path, pool);
226 }
227
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)
234 {
235   struct compat_report_baton *crb = report_baton;
236
237   return crb->reporter->link_path(crb->baton, path, url, revision,
238                                   svn_depth_infinity, start_empty,
239                                   NULL, pool);
240 }
241
242 static svn_error_t *compat_finish_report(void *report_baton,
243                                          apr_pool_t *pool)
244 {
245   struct compat_report_baton *crb = report_baton;
246
247   return crb->reporter->finish_report(crb->baton, pool);
248 }
249
250 static svn_error_t *compat_abort_report(void *report_baton,
251                                         apr_pool_t *pool)
252 {
253   struct compat_report_baton *crb = report_baton;
254
255   return crb->reporter->abort_report(crb->baton, pool);
256 }
257
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
264 };
265
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)
271 {
272   struct compat_report_baton *crb = apr_palloc(pool, sizeof(*crb));
273   crb->reporter = wrapped;
274   crb->baton = wrapped_baton;
275
276   *reporter = &compat_reporter;
277   *baton = crb;
278 }
279
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)
289 {
290   const svn_ra_reporter3_t *reporter3;
291   void *baton3;
292   svn_depth_t depth = SVN_DEPTH_INFINITY_OR_FILES(recurse);
293
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);
301
302   return SVN_NO_ERROR;
303 }
304
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)
315 {
316   const svn_ra_reporter3_t *reporter3;
317   void *baton3;
318   svn_depth_t depth = SVN_DEPTH_INFINITY_OR_FILES(recurse);
319
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 */));
327
328   compat_wrap_reporter(reporter, report_baton, reporter3, baton3, pool);
329
330   return SVN_NO_ERROR;
331 }
332
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)
342 {
343   const svn_ra_reporter3_t *reporter3;
344   void *baton3;
345   svn_depth_t depth = SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse);
346
347   SVN_ERR(VTBL.do_status(session_baton, &reporter3, &baton3, status_target,
348                          revision, depth, editor, status_baton, pool));
349
350   compat_wrap_reporter(reporter, report_baton, reporter3, baton3, pool);
351
352   return SVN_NO_ERROR;
353 }
354
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)
366 {
367   const svn_ra_reporter3_t *reporter3;
368   void *baton3;
369   svn_depth_t depth = SVN_DEPTH_INFINITY_OR_FILES(recurse);
370
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));
374
375   compat_wrap_reporter(reporter, report_baton, reporter3, baton3, pool);
376
377   return SVN_NO_ERROR;
378 }
379
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)
389 {
390   svn_log_entry_receiver_t receiver2;
391   void *receiver2_baton;
392
393   svn_compat_wrap_log_receiver(&receiver2, &receiver2_baton,
394                                receiver, receiver_baton,
395                                pool);
396
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);
402 }
403
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)
409 {
410   return VTBL.check_path(session_baton, path, revision, kind, pool);
411 }
412
413 static svn_error_t *compat_get_uuid(void *session_baton,
414                                     const char **uuid,
415                                     apr_pool_t *pool)
416 {
417   return VTBL.get_uuid(session_baton, uuid, pool);
418 }
419
420 static svn_error_t *compat_get_repos_root(void *session_baton,
421                                           const char **url,
422                                           apr_pool_t *pool)
423 {
424   return VTBL.get_repos_root(session_baton, url, pool);
425 }
426
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)
433 {
434   return VTBL.get_locations(session_baton, locations, path, peg_revision,
435                             location_revs, pool);
436 }
437
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)
445 {
446   svn_file_rev_handler_t handler2;
447   void *handler2_baton;
448
449   svn_compat_wrap_file_rev_handler(&handler2, &handler2_baton,
450                                    handler, handler_baton,
451                                    pool);
452
453   return VTBL.get_file_revs(session_baton, path, start, end,
454                             FALSE, /* include merged revisions */
455                             handler2, handler2_baton, pool);
456 }
457
458 static const svn_version_t *compat_get_version(void)
459 {
460   return VTBL.get_version();
461 }
462
463
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
487 };
488
489 svn_error_t *
490 COMPAT_INITFUNC(int abi_version,
491                 apr_pool_t *pool,
492                 apr_hash_t *hash)
493 {
494   const svn_ra__vtable_t *vtable;
495   const char * const * schemes;
496
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);
502
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));
507
508   schemes = VTBL.get_schemes(pool);
509
510   for (; *schemes != NULL; ++schemes)
511     apr_hash_set(hash, *schemes, APR_HASH_KEY_STRING, &compat_plugin);
512
513   return SVN_NO_ERROR;
514 }