]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/subversion/subversion/libsvn_client/deprecated.c
MFC r275385 (by bapt):
[FreeBSD/stable/10.git] / contrib / subversion / subversion / libsvn_client / deprecated.c
1 /*
2  * deprecated.c:  holding file for all deprecated APIs.
3  *                "we can't lose 'em, but we can shun 'em!"
4  *
5  * ====================================================================
6  *    Licensed to the Apache Software Foundation (ASF) under one
7  *    or more contributor license agreements.  See the NOTICE file
8  *    distributed with this work for additional information
9  *    regarding copyright ownership.  The ASF licenses this file
10  *    to you under the Apache License, Version 2.0 (the
11  *    "License"); you may not use this file except in compliance
12  *    with the License.  You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  *    Unless required by applicable law or agreed to in writing,
17  *    software distributed under the License is distributed on an
18  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19  *    KIND, either express or implied.  See the License for the
20  *    specific language governing permissions and limitations
21  *    under the License.
22  * ====================================================================
23  */
24
25 /* ==================================================================== */
26
27
28 \f
29 /*** Includes. ***/
30
31 /* We define this here to remove any further warnings about the usage of
32    deprecated functions in this file. */
33 #define SVN_DEPRECATED
34
35 #include <string.h>
36 #include "svn_client.h"
37 #include "svn_path.h"
38 #include "svn_compat.h"
39 #include "svn_hash.h"
40 #include "svn_props.h"
41 #include "svn_utf.h"
42 #include "svn_string.h"
43 #include "svn_pools.h"
44
45 #include "client.h"
46 #include "mergeinfo.h"
47
48 #include "private/svn_opt_private.h"
49 #include "private/svn_wc_private.h"
50 #include "svn_private_config.h"
51
52
53
54 \f
55 /*** Code. ***/
56
57
58 /* Baton for capture_commit_info() */
59 struct capture_baton_t {
60   svn_commit_info_t **info;
61   apr_pool_t *pool;
62 };
63
64
65 /* Callback which implements svn_commit_callback2_t for use with some
66    backward compat functions. */
67 static svn_error_t *
68 capture_commit_info(const svn_commit_info_t *commit_info,
69                     void *baton,
70                     apr_pool_t *pool)
71 {
72   struct capture_baton_t *cb = baton;
73
74   *(cb->info) = svn_commit_info_dup(commit_info, cb->pool);
75
76   return SVN_NO_ERROR;
77 }
78
79
80 /*** From add.c ***/
81 svn_error_t *
82 svn_client_add4(const char *path,
83                 svn_depth_t depth,
84                 svn_boolean_t force,
85                 svn_boolean_t no_ignore,
86                 svn_boolean_t add_parents,
87                 svn_client_ctx_t *ctx,
88                 apr_pool_t *pool)
89 {
90   return svn_client_add5(path, depth, force, no_ignore, FALSE, add_parents,
91                          ctx, pool);
92 }
93
94 svn_error_t *
95 svn_client_add3(const char *path,
96                 svn_boolean_t recursive,
97                 svn_boolean_t force,
98                 svn_boolean_t no_ignore,
99                 svn_client_ctx_t *ctx,
100                 apr_pool_t *pool)
101 {
102   return svn_client_add4(path, SVN_DEPTH_INFINITY_OR_EMPTY(recursive),
103                          force, no_ignore, FALSE, ctx,
104                          pool);
105 }
106
107 svn_error_t *
108 svn_client_add2(const char *path,
109                 svn_boolean_t recursive,
110                 svn_boolean_t force,
111                 svn_client_ctx_t *ctx,
112                 apr_pool_t *pool)
113 {
114   return svn_client_add3(path, recursive, force, FALSE, ctx, pool);
115 }
116
117 svn_error_t *
118 svn_client_add(const char *path,
119                svn_boolean_t recursive,
120                svn_client_ctx_t *ctx,
121                apr_pool_t *pool)
122 {
123   return svn_client_add3(path, recursive, FALSE, FALSE, ctx, pool);
124 }
125
126 svn_error_t *
127 svn_client_mkdir3(svn_commit_info_t **commit_info_p,
128                   const apr_array_header_t *paths,
129                   svn_boolean_t make_parents,
130                   const apr_hash_t *revprop_table,
131                   svn_client_ctx_t *ctx,
132                   apr_pool_t *pool)
133 {
134   struct capture_baton_t cb;
135
136   cb.info = commit_info_p;
137   cb.pool = pool;
138
139   return svn_client_mkdir4(paths, make_parents, revprop_table,
140                            capture_commit_info, &cb, ctx, pool);
141 }
142
143 svn_error_t *
144 svn_client_mkdir2(svn_commit_info_t **commit_info_p,
145                   const apr_array_header_t *paths,
146                   svn_client_ctx_t *ctx,
147                   apr_pool_t *pool)
148 {
149   return svn_client_mkdir3(commit_info_p, paths, FALSE, NULL, ctx, pool);
150 }
151
152
153 svn_error_t *
154 svn_client_mkdir(svn_client_commit_info_t **commit_info_p,
155                  const apr_array_header_t *paths,
156                  svn_client_ctx_t *ctx,
157                  apr_pool_t *pool)
158 {
159   svn_commit_info_t *commit_info = NULL;
160   svn_error_t *err;
161
162   err = svn_client_mkdir2(&commit_info, paths, ctx, pool);
163   /* These structs have the same layout for the common fields. */
164   *commit_info_p = (svn_client_commit_info_t *) commit_info;
165   return svn_error_trace(err);
166 }
167
168 /*** From blame.c ***/
169
170 struct blame_receiver_wrapper_baton2 {
171   void *baton;
172   svn_client_blame_receiver2_t receiver;
173 };
174
175 static svn_error_t *
176 blame_wrapper_receiver2(void *baton,
177    svn_revnum_t start_revnum,
178    svn_revnum_t end_revnum,
179    apr_int64_t line_no,
180    svn_revnum_t revision,
181    apr_hash_t *rev_props,
182    svn_revnum_t merged_revision,
183    apr_hash_t *merged_rev_props,
184    const char *merged_path,
185    const char *line,
186    svn_boolean_t local_change,
187    apr_pool_t *pool)
188 {
189   struct blame_receiver_wrapper_baton2 *brwb = baton;
190   const char *author = NULL;
191   const char *date = NULL;
192   const char *merged_author = NULL;
193   const char *merged_date = NULL;
194
195   if (rev_props != NULL)
196     {
197       author = svn_prop_get_value(rev_props, SVN_PROP_REVISION_AUTHOR);
198       date = svn_prop_get_value(rev_props, SVN_PROP_REVISION_DATE);
199     }
200   if (merged_rev_props != NULL)
201     {
202       merged_author = svn_prop_get_value(merged_rev_props,
203                                          SVN_PROP_REVISION_AUTHOR);
204       merged_date = svn_prop_get_value(merged_rev_props,
205                                        SVN_PROP_REVISION_DATE);
206     }
207
208   if (brwb->receiver)
209     return brwb->receiver(brwb->baton, line_no, revision, author, date,
210                           merged_revision, merged_author, merged_date,
211                           merged_path, line, pool);
212
213   return SVN_NO_ERROR;
214 }
215
216 svn_error_t *
217 svn_client_blame4(const char *target,
218                   const svn_opt_revision_t *peg_revision,
219                   const svn_opt_revision_t *start,
220                   const svn_opt_revision_t *end,
221                   const svn_diff_file_options_t *diff_options,
222                   svn_boolean_t ignore_mime_type,
223                   svn_boolean_t include_merged_revisions,
224                   svn_client_blame_receiver2_t receiver,
225                   void *receiver_baton,
226                   svn_client_ctx_t *ctx,
227                   apr_pool_t *pool)
228 {
229   struct blame_receiver_wrapper_baton2 baton;
230
231   baton.receiver = receiver;
232   baton.baton = receiver_baton;
233
234   return svn_client_blame5(target, peg_revision, start, end, diff_options,
235                            ignore_mime_type, include_merged_revisions,
236                            blame_wrapper_receiver2, &baton, ctx, pool);
237 }
238
239
240 /* Baton for use with wrap_blame_receiver */
241 struct blame_receiver_wrapper_baton {
242   void *baton;
243   svn_client_blame_receiver_t receiver;
244 };
245
246 /* This implements svn_client_blame_receiver2_t */
247 static svn_error_t *
248 blame_wrapper_receiver(void *baton,
249                        apr_int64_t line_no,
250                        svn_revnum_t revision,
251                        const char *author,
252                        const char *date,
253                        svn_revnum_t merged_revision,
254                        const char *merged_author,
255                        const char *merged_date,
256                        const char *merged_path,
257                        const char *line,
258                        apr_pool_t *pool)
259 {
260   struct blame_receiver_wrapper_baton *brwb = baton;
261
262   if (brwb->receiver)
263     return brwb->receiver(brwb->baton,
264                           line_no, revision, author, date, line, pool);
265
266   return SVN_NO_ERROR;
267 }
268
269 static void
270 wrap_blame_receiver(svn_client_blame_receiver2_t *receiver2,
271                     void **receiver2_baton,
272                     svn_client_blame_receiver_t receiver,
273                     void *receiver_baton,
274                     apr_pool_t *pool)
275 {
276   struct blame_receiver_wrapper_baton *brwb = apr_palloc(pool, sizeof(*brwb));
277
278   /* Set the user provided old format callback in the baton. */
279   brwb->baton = receiver_baton;
280   brwb->receiver = receiver;
281
282   *receiver2_baton = brwb;
283   *receiver2 = blame_wrapper_receiver;
284 }
285
286 svn_error_t *
287 svn_client_blame3(const char *target,
288                   const svn_opt_revision_t *peg_revision,
289                   const svn_opt_revision_t *start,
290                   const svn_opt_revision_t *end,
291                   const svn_diff_file_options_t *diff_options,
292                   svn_boolean_t ignore_mime_type,
293                   svn_client_blame_receiver_t receiver,
294                   void *receiver_baton,
295                   svn_client_ctx_t *ctx,
296                   apr_pool_t *pool)
297 {
298   svn_client_blame_receiver2_t receiver2;
299   void *receiver2_baton;
300
301   wrap_blame_receiver(&receiver2, &receiver2_baton, receiver, receiver_baton,
302                       pool);
303
304   return svn_client_blame4(target, peg_revision, start, end, diff_options,
305                            ignore_mime_type, FALSE, receiver2, receiver2_baton,
306                            ctx, pool);
307 }
308
309 /* svn_client_blame3 guarantees 'no EOL chars' as part of the receiver
310    LINE argument.  Older versions depend on the fact that if a CR is
311    required, that CR is already part of the LINE data.
312
313    Because of this difference, we need to trap old receivers and append
314    a CR to LINE before passing it on to the actual receiver on platforms
315    which want CRLF line termination.
316
317 */
318
319 struct wrapped_receiver_baton_s
320 {
321   svn_client_blame_receiver_t orig_receiver;
322   void *orig_baton;
323 };
324
325 static svn_error_t *
326 wrapped_receiver(void *baton,
327                  apr_int64_t line_no,
328                  svn_revnum_t revision,
329                  const char *author,
330                  const char *date,
331                  const char *line,
332                  apr_pool_t *pool)
333 {
334   struct wrapped_receiver_baton_s *b = baton;
335   svn_stringbuf_t *expanded_line = svn_stringbuf_create(line, pool);
336
337   svn_stringbuf_appendbyte(expanded_line, '\r');
338
339   return b->orig_receiver(b->orig_baton, line_no, revision, author,
340                           date, expanded_line->data, pool);
341 }
342
343 static void
344 wrap_pre_blame3_receiver(svn_client_blame_receiver_t *receiver,
345                          void **receiver_baton,
346                          apr_pool_t *pool)
347 {
348   if (sizeof(APR_EOL_STR) == 3)
349     {
350       struct wrapped_receiver_baton_s *b = apr_palloc(pool,sizeof(*b));
351
352       b->orig_receiver = *receiver;
353       b->orig_baton = *receiver_baton;
354
355       *receiver_baton = b;
356       *receiver = wrapped_receiver;
357     }
358 }
359
360 svn_error_t *
361 svn_client_blame2(const char *target,
362                   const svn_opt_revision_t *peg_revision,
363                   const svn_opt_revision_t *start,
364                   const svn_opt_revision_t *end,
365                   svn_client_blame_receiver_t receiver,
366                   void *receiver_baton,
367                   svn_client_ctx_t *ctx,
368                   apr_pool_t *pool)
369 {
370   wrap_pre_blame3_receiver(&receiver, &receiver_baton, pool);
371   return svn_client_blame3(target, peg_revision, start, end,
372                            svn_diff_file_options_create(pool), FALSE,
373                            receiver, receiver_baton, ctx, pool);
374 }
375 svn_error_t *
376 svn_client_blame(const char *target,
377                  const svn_opt_revision_t *start,
378                  const svn_opt_revision_t *end,
379                  svn_client_blame_receiver_t receiver,
380                  void *receiver_baton,
381                  svn_client_ctx_t *ctx,
382                  apr_pool_t *pool)
383 {
384   wrap_pre_blame3_receiver(&receiver, &receiver_baton, pool);
385   return svn_client_blame2(target, end, start, end,
386                            receiver, receiver_baton, ctx, pool);
387 }
388
389 /*** From cmdline.c ***/
390 svn_error_t *
391 svn_client_args_to_target_array(apr_array_header_t **targets_p,
392                                 apr_getopt_t *os,
393                                 const apr_array_header_t *known_targets,
394                                 svn_client_ctx_t *ctx,
395                                 apr_pool_t *pool)
396 {
397   return svn_client_args_to_target_array2(targets_p, os, known_targets, ctx,
398                                           FALSE, pool);
399 }
400
401 /*** From commit.c ***/
402 svn_error_t *
403 svn_client_import4(const char *path,
404                    const char *url,
405                    svn_depth_t depth,
406                    svn_boolean_t no_ignore,
407                    svn_boolean_t ignore_unknown_node_types,
408                    const apr_hash_t *revprop_table,
409                    svn_commit_callback2_t commit_callback,
410                    void *commit_baton,
411                    svn_client_ctx_t *ctx,
412                    apr_pool_t *pool)
413 {
414   return svn_error_trace(svn_client_import5(path, url, depth, no_ignore,
415                                             FALSE, ignore_unknown_node_types,
416                                             revprop_table,
417                                             NULL, NULL,
418                                             commit_callback, commit_baton,
419                                             ctx, pool));
420 }
421
422
423 svn_error_t *
424 svn_client_import3(svn_commit_info_t **commit_info_p,
425                    const char *path,
426                    const char *url,
427                    svn_depth_t depth,
428                    svn_boolean_t no_ignore,
429                    svn_boolean_t ignore_unknown_node_types,
430                    const apr_hash_t *revprop_table,
431                    svn_client_ctx_t *ctx,
432                    apr_pool_t *pool)
433 {
434   struct capture_baton_t cb;
435
436   cb.info = commit_info_p;
437   cb.pool = pool;
438
439   return svn_client_import4(path, url, depth, no_ignore,
440                             ignore_unknown_node_types, revprop_table,
441                             capture_commit_info, &cb, ctx, pool);
442 }
443
444 svn_error_t *
445 svn_client_import2(svn_commit_info_t **commit_info_p,
446                    const char *path,
447                    const char *url,
448                    svn_boolean_t nonrecursive,
449                    svn_boolean_t no_ignore,
450                    svn_client_ctx_t *ctx,
451                    apr_pool_t *pool)
452 {
453   return svn_client_import3(commit_info_p,
454                             path, url,
455                             SVN_DEPTH_INFINITY_OR_FILES(! nonrecursive),
456                             no_ignore, FALSE, NULL, ctx, pool);
457 }
458
459 svn_error_t *
460 svn_client_import(svn_client_commit_info_t **commit_info_p,
461                   const char *path,
462                   const char *url,
463                   svn_boolean_t nonrecursive,
464                   svn_client_ctx_t *ctx,
465                   apr_pool_t *pool)
466 {
467   svn_commit_info_t *commit_info = NULL;
468   svn_error_t *err;
469
470   err = svn_client_import2(&commit_info,
471                            path, url, nonrecursive,
472                            FALSE, ctx, pool);
473   /* These structs have the same layout for the common fields. */
474   *commit_info_p = (svn_client_commit_info_t *) commit_info;
475   return svn_error_trace(err);
476 }
477
478
479 /* Wrapper notify_func2 function and baton for downgrading
480    svn_wc_notify_commit_copied and svn_wc_notify_commit_copied_replaced
481    to svn_wc_notify_commit_added and svn_wc_notify_commit_replaced,
482    respectively. */
483 struct downgrade_commit_copied_notify_baton
484 {
485   svn_wc_notify_func2_t orig_notify_func2;
486   void *orig_notify_baton2;
487 };
488
489 static void
490 downgrade_commit_copied_notify_func(void *baton,
491                                     const svn_wc_notify_t *notify,
492                                     apr_pool_t *pool)
493 {
494   struct downgrade_commit_copied_notify_baton *b = baton;
495
496   if (notify->action == svn_wc_notify_commit_copied)
497     {
498       svn_wc_notify_t *my_notify = svn_wc_dup_notify(notify, pool);
499       my_notify->action = svn_wc_notify_commit_added;
500       notify = my_notify;
501     }
502   else if (notify->action == svn_wc_notify_commit_copied_replaced)
503     {
504       svn_wc_notify_t *my_notify = svn_wc_dup_notify(notify, pool);
505       my_notify->action = svn_wc_notify_commit_replaced;
506       notify = my_notify;
507     }
508
509   /* Call the wrapped notification system (if any) with MY_NOTIFY,
510      which is either the original NOTIFY object, or a tweaked deep
511      copy thereof. */
512   if (b->orig_notify_func2)
513     b->orig_notify_func2(b->orig_notify_baton2, notify, pool);
514 }
515
516 svn_error_t *
517 svn_client_commit5(const apr_array_header_t *targets,
518                    svn_depth_t depth,
519                    svn_boolean_t keep_locks,
520                    svn_boolean_t keep_changelists,
521                    svn_boolean_t commit_as_operations,
522                    const apr_array_header_t *changelists,
523                    const apr_hash_t *revprop_table,
524                    svn_commit_callback2_t commit_callback,
525                    void *commit_baton,
526                    svn_client_ctx_t *ctx,
527                    apr_pool_t *pool)
528 {
529   return svn_client_commit6(targets, depth, keep_locks, keep_changelists,
530                             commit_as_operations,
531                             FALSE,  /* include_file_externals */
532                             FALSE, /* include_dir_externals */
533                             changelists, revprop_table, commit_callback,
534                             commit_baton, ctx, pool);
535 }
536
537 svn_error_t *
538 svn_client_commit4(svn_commit_info_t **commit_info_p,
539                    const apr_array_header_t *targets,
540                    svn_depth_t depth,
541                    svn_boolean_t keep_locks,
542                    svn_boolean_t keep_changelists,
543                    const apr_array_header_t *changelists,
544                    const apr_hash_t *revprop_table,
545                    svn_client_ctx_t *ctx,
546                    apr_pool_t *pool)
547 {
548   struct capture_baton_t cb;
549   struct downgrade_commit_copied_notify_baton notify_baton;
550   svn_error_t *err;
551
552   notify_baton.orig_notify_func2 = ctx->notify_func2;
553   notify_baton.orig_notify_baton2 = ctx->notify_baton2;
554
555   *commit_info_p = NULL;
556   cb.info = commit_info_p;
557   cb.pool = pool;
558
559   /* Swap out the notification system (if any) with a thin filtering
560      wrapper. */
561   if (ctx->notify_func2)
562     {
563       ctx->notify_func2 = downgrade_commit_copied_notify_func;
564       ctx->notify_baton2 = &notify_baton;
565     }
566
567   err = svn_client_commit5(targets, depth, keep_locks, keep_changelists, FALSE,
568                            changelists, revprop_table,
569                            capture_commit_info, &cb, ctx, pool);
570
571   /* Ensure that the original notification system is in place. */
572   ctx->notify_func2 = notify_baton.orig_notify_func2;
573   ctx->notify_baton2 = notify_baton.orig_notify_baton2;
574
575   SVN_ERR(err);
576
577   if (! *commit_info_p)
578     *commit_info_p = svn_create_commit_info(pool);
579
580   return SVN_NO_ERROR;
581 }
582
583 svn_error_t *
584 svn_client_commit3(svn_commit_info_t **commit_info_p,
585                    const apr_array_header_t *targets,
586                    svn_boolean_t recurse,
587                    svn_boolean_t keep_locks,
588                    svn_client_ctx_t *ctx,
589                    apr_pool_t *pool)
590 {
591   svn_depth_t depth = SVN_DEPTH_INFINITY_OR_EMPTY(recurse);
592
593   return svn_client_commit4(commit_info_p, targets, depth, keep_locks,
594                             FALSE, NULL, NULL, ctx, pool);
595 }
596
597 svn_error_t *
598 svn_client_commit2(svn_client_commit_info_t **commit_info_p,
599                    const apr_array_header_t *targets,
600                    svn_boolean_t recurse,
601                    svn_boolean_t keep_locks,
602                    svn_client_ctx_t *ctx,
603                    apr_pool_t *pool)
604 {
605   svn_commit_info_t *commit_info = NULL;
606   svn_error_t *err;
607
608   err = svn_client_commit3(&commit_info, targets, recurse, keep_locks,
609                            ctx, pool);
610   /* These structs have the same layout for the common fields. */
611   *commit_info_p = (svn_client_commit_info_t *) commit_info;
612   return svn_error_trace(err);
613 }
614
615 svn_error_t *
616 svn_client_commit(svn_client_commit_info_t **commit_info_p,
617                   const apr_array_header_t *targets,
618                   svn_boolean_t nonrecursive,
619                   svn_client_ctx_t *ctx,
620                   apr_pool_t *pool)
621 {
622   return svn_client_commit2(commit_info_p, targets,
623                             ! nonrecursive,
624                             TRUE,
625                             ctx, pool);
626 }
627
628 /*** From copy.c ***/
629 svn_error_t *
630 svn_client_copy6(const apr_array_header_t *sources,
631                  const char *dst_path,
632                  svn_boolean_t copy_as_child,
633                  svn_boolean_t make_parents,
634                  svn_boolean_t ignore_externals,
635                  const apr_hash_t *revprop_table,
636                  svn_commit_callback2_t commit_callback,
637                  void *commit_baton,
638                  svn_client_ctx_t *ctx,
639                  apr_pool_t *pool)
640 {
641   return svn_error_trace(svn_client_copy7(sources, dst_path, copy_as_child,
642                                           make_parents, ignore_externals,
643                                           FALSE /* metadata_only */,
644                                           FALSE /* pin_externals */,
645                                           NULL /* externals_to_pin */,
646                                           revprop_table,
647                                           commit_callback, commit_baton,
648                                           ctx, pool));
649 }
650
651 svn_error_t *
652 svn_client_copy5(svn_commit_info_t **commit_info_p,
653                  const apr_array_header_t *sources,
654                  const char *dst_path,
655                  svn_boolean_t copy_as_child,
656                  svn_boolean_t make_parents,
657                  svn_boolean_t ignore_externals,
658                  const apr_hash_t *revprop_table,
659                  svn_client_ctx_t *ctx,
660                  apr_pool_t *pool)
661 {
662   struct capture_baton_t cb;
663
664   cb.info = commit_info_p;
665   cb.pool = pool;
666
667   return svn_client_copy6(sources, dst_path, copy_as_child, make_parents,
668                           ignore_externals, revprop_table,
669                           capture_commit_info, &cb, ctx, pool);
670 }
671
672 svn_error_t *
673 svn_client_copy4(svn_commit_info_t **commit_info_p,
674                  const apr_array_header_t *sources,
675                  const char *dst_path,
676                  svn_boolean_t copy_as_child,
677                  svn_boolean_t make_parents,
678                  const apr_hash_t *revprop_table,
679                  svn_client_ctx_t *ctx,
680                  apr_pool_t *pool)
681 {
682   return svn_client_copy5(commit_info_p, sources, dst_path, copy_as_child,
683                           make_parents, FALSE, revprop_table, ctx, pool);
684 }
685
686 svn_error_t *
687 svn_client_copy3(svn_commit_info_t **commit_info_p,
688                  const char *src_path,
689                  const svn_opt_revision_t *src_revision,
690                  const char *dst_path,
691                  svn_client_ctx_t *ctx,
692                  apr_pool_t *pool)
693 {
694   apr_array_header_t *sources = apr_array_make(pool, 1,
695                                   sizeof(const svn_client_copy_source_t *));
696   svn_client_copy_source_t copy_source;
697
698   copy_source.path = src_path;
699   copy_source.revision = src_revision;
700   copy_source.peg_revision = src_revision;
701
702   APR_ARRAY_PUSH(sources, const svn_client_copy_source_t *) = &copy_source;
703
704   return svn_client_copy4(commit_info_p, sources, dst_path, FALSE, FALSE,
705                           NULL, ctx, pool);
706 }
707
708 svn_error_t *
709 svn_client_copy2(svn_commit_info_t **commit_info_p,
710                  const char *src_path,
711                  const svn_opt_revision_t *src_revision,
712                  const char *dst_path,
713                  svn_client_ctx_t *ctx,
714                  apr_pool_t *pool)
715 {
716   svn_error_t *err;
717
718   err = svn_client_copy3(commit_info_p, src_path, src_revision,
719                          dst_path, ctx, pool);
720
721   /* If the target exists, try to copy the source as a child of the target.
722      This will obviously fail if target is not a directory, but that's exactly
723      what we want. */
724   if (err && (err->apr_err == SVN_ERR_ENTRY_EXISTS
725               || err->apr_err == SVN_ERR_FS_ALREADY_EXISTS))
726     {
727       const char *src_basename = svn_path_basename(src_path, pool);
728
729       svn_error_clear(err);
730
731       return svn_client_copy3(commit_info_p, src_path, src_revision,
732                               svn_path_join(dst_path, src_basename, pool),
733                               ctx, pool);
734     }
735
736   return svn_error_trace(err);
737 }
738
739 svn_error_t *
740 svn_client_copy(svn_client_commit_info_t **commit_info_p,
741                 const char *src_path,
742                 const svn_opt_revision_t *src_revision,
743                 const char *dst_path,
744                 svn_client_ctx_t *ctx,
745                 apr_pool_t *pool)
746 {
747   svn_commit_info_t *commit_info = NULL;
748   svn_error_t *err;
749
750   err = svn_client_copy2(&commit_info, src_path, src_revision, dst_path,
751                          ctx, pool);
752   /* These structs have the same layout for the common fields. */
753   *commit_info_p = (svn_client_commit_info_t *) commit_info;
754   return svn_error_trace(err);
755 }
756
757 svn_error_t *
758 svn_client_move6(const apr_array_header_t *src_paths,
759                  const char *dst_path,
760                  svn_boolean_t move_as_child,
761                  svn_boolean_t make_parents,
762                  const apr_hash_t *revprop_table,
763                  svn_commit_callback2_t commit_callback,
764                  void *commit_baton,
765                  svn_client_ctx_t *ctx,
766                  apr_pool_t *pool)
767 {
768   return svn_error_trace(svn_client_move7(src_paths, dst_path,
769                                           move_as_child, make_parents,
770                                           TRUE /* allow_mixed_revisions */,
771                                           FALSE /* metadata_only */,
772                                           revprop_table,
773                                           commit_callback, commit_baton,
774                                           ctx, pool));
775 }
776
777 svn_error_t *
778 svn_client_move5(svn_commit_info_t **commit_info_p,
779                  const apr_array_header_t *src_paths,
780                  const char *dst_path,
781                  svn_boolean_t force,
782                  svn_boolean_t move_as_child,
783                  svn_boolean_t make_parents,
784                  const apr_hash_t *revprop_table,
785                  svn_client_ctx_t *ctx,
786                  apr_pool_t *pool)
787 {
788   struct capture_baton_t cb;
789
790   cb.info = commit_info_p;
791   cb.pool = pool;
792
793   return svn_client_move6(src_paths, dst_path, move_as_child,
794                           make_parents, revprop_table,
795                           capture_commit_info, &cb, ctx, pool);
796 }
797
798 svn_error_t *
799 svn_client_move4(svn_commit_info_t **commit_info_p,
800                  const char *src_path,
801                  const char *dst_path,
802                  svn_boolean_t force,
803                  svn_client_ctx_t *ctx,
804                  apr_pool_t *pool)
805 {
806   apr_array_header_t *src_paths =
807     apr_array_make(pool, 1, sizeof(const char *));
808   APR_ARRAY_PUSH(src_paths, const char *) = src_path;
809
810
811   return svn_client_move5(commit_info_p, src_paths, dst_path, force, FALSE,
812                           FALSE, NULL, ctx, pool);
813 }
814
815 svn_error_t *
816 svn_client_move3(svn_commit_info_t **commit_info_p,
817                  const char *src_path,
818                  const char *dst_path,
819                  svn_boolean_t force,
820                  svn_client_ctx_t *ctx,
821                  apr_pool_t *pool)
822 {
823   svn_error_t *err;
824
825   err = svn_client_move4(commit_info_p, src_path, dst_path, force, ctx, pool);
826
827   /* If the target exists, try to move the source as a child of the target.
828      This will obviously fail if target is not a directory, but that's exactly
829      what we want. */
830   if (err && (err->apr_err == SVN_ERR_ENTRY_EXISTS
831               || err->apr_err == SVN_ERR_FS_ALREADY_EXISTS))
832     {
833       const char *src_basename = svn_path_basename(src_path, pool);
834
835       svn_error_clear(err);
836
837       return svn_client_move4(commit_info_p, src_path,
838                               svn_path_join(dst_path, src_basename, pool),
839                               force, ctx, pool);
840     }
841
842   return svn_error_trace(err);
843 }
844
845 svn_error_t *
846 svn_client_move2(svn_client_commit_info_t **commit_info_p,
847                  const char *src_path,
848                  const char *dst_path,
849                  svn_boolean_t force,
850                  svn_client_ctx_t *ctx,
851                  apr_pool_t *pool)
852 {
853   svn_commit_info_t *commit_info = NULL;
854   svn_error_t *err;
855
856   err = svn_client_move3(&commit_info, src_path, dst_path, force, ctx, pool);
857   /* These structs have the same layout for the common fields. */
858   *commit_info_p = (svn_client_commit_info_t *) commit_info;
859   return svn_error_trace(err);
860 }
861
862
863 svn_error_t *
864 svn_client_move(svn_client_commit_info_t **commit_info_p,
865                 const char *src_path,
866                 const svn_opt_revision_t *src_revision,
867                 const char *dst_path,
868                 svn_boolean_t force,
869                 svn_client_ctx_t *ctx,
870                 apr_pool_t *pool)
871 {
872   /* It doesn't make sense to specify revisions in a move. */
873
874   /* ### todo: this check could fail wrongly.  For example,
875      someone could pass in an svn_opt_revision_number that just
876      happens to be the HEAD.  It's fair enough to punt then, IMHO,
877      and just demand that the user not specify a revision at all;
878      beats mucking up this function with RA calls and such. */
879   if (src_revision->kind != svn_opt_revision_unspecified
880       && src_revision->kind != svn_opt_revision_head)
881     {
882       return svn_error_create
883         (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
884          _("Cannot specify revisions (except HEAD) with move operations"));
885     }
886
887   return svn_client_move2(commit_info_p, src_path, dst_path, force, ctx, pool);
888 }
889
890 /*** From delete.c ***/
891 svn_error_t *
892 svn_client_delete3(svn_commit_info_t **commit_info_p,
893                    const apr_array_header_t *paths,
894                    svn_boolean_t force,
895                    svn_boolean_t keep_local,
896                    const apr_hash_t *revprop_table,
897                    svn_client_ctx_t *ctx,
898                    apr_pool_t *pool)
899 {
900   struct capture_baton_t cb;
901
902   cb.info = commit_info_p;
903   cb.pool = pool;
904
905   return svn_client_delete4(paths, force, keep_local, revprop_table,
906                             capture_commit_info, &cb, ctx, pool);
907 }
908
909 svn_error_t *
910 svn_client_delete2(svn_commit_info_t **commit_info_p,
911                    const apr_array_header_t *paths,
912                    svn_boolean_t force,
913                    svn_client_ctx_t *ctx,
914                    apr_pool_t *pool)
915 {
916   return svn_client_delete3(commit_info_p, paths, force, FALSE, NULL,
917                             ctx, pool);
918 }
919
920 svn_error_t *
921 svn_client_delete(svn_client_commit_info_t **commit_info_p,
922                   const apr_array_header_t *paths,
923                   svn_boolean_t force,
924                   svn_client_ctx_t *ctx,
925                   apr_pool_t *pool)
926 {
927   svn_commit_info_t *commit_info = NULL;
928   svn_error_t *err = NULL;
929
930   err = svn_client_delete2(&commit_info, paths, force, ctx, pool);
931   /* These structs have the same layout for the common fields. */
932   *commit_info_p = (svn_client_commit_info_t *) commit_info;
933   return svn_error_trace(err);
934 }
935
936 /*** From diff.c ***/
937
938 svn_error_t *
939 svn_client_diff5(const apr_array_header_t *diff_options,
940                  const char *path1,
941                  const svn_opt_revision_t *revision1,
942                  const char *path2,
943                  const svn_opt_revision_t *revision2,
944                  const char *relative_to_dir,
945                  svn_depth_t depth,
946                  svn_boolean_t ignore_ancestry,
947                  svn_boolean_t no_diff_deleted,
948                  svn_boolean_t show_copies_as_adds,
949                  svn_boolean_t ignore_content_type,
950                  svn_boolean_t use_git_diff_format,
951                  const char *header_encoding,
952                  apr_file_t *outfile,
953                  apr_file_t *errfile,
954                  const apr_array_header_t *changelists,
955                  svn_client_ctx_t *ctx,
956                  apr_pool_t *pool)
957 {
958   svn_stream_t *outstream = svn_stream_from_aprfile2(outfile, TRUE, pool);
959   svn_stream_t *errstream = svn_stream_from_aprfile2(errfile, TRUE, pool);
960
961   return svn_client_diff6(diff_options, path1, revision1, path2,
962                           revision2, relative_to_dir, depth,
963                           ignore_ancestry, FALSE /* no_diff_added */,
964                           no_diff_deleted, show_copies_as_adds,
965                           ignore_content_type, FALSE /* ignore_properties */,
966                           FALSE /* properties_only */, use_git_diff_format,
967                           header_encoding,
968                           outstream, errstream, changelists, ctx, pool);
969 }
970
971 svn_error_t *
972 svn_client_diff4(const apr_array_header_t *options,
973                  const char *path1,
974                  const svn_opt_revision_t *revision1,
975                  const char *path2,
976                  const svn_opt_revision_t *revision2,
977                  const char *relative_to_dir,
978                  svn_depth_t depth,
979                  svn_boolean_t ignore_ancestry,
980                  svn_boolean_t no_diff_deleted,
981                  svn_boolean_t ignore_content_type,
982                  const char *header_encoding,
983                  apr_file_t *outfile,
984                  apr_file_t *errfile,
985                  const apr_array_header_t *changelists,
986                  svn_client_ctx_t *ctx,
987                  apr_pool_t *pool)
988 {
989   return svn_client_diff5(options, path1, revision1, path2,
990                           revision2, relative_to_dir, depth,
991                           ignore_ancestry, no_diff_deleted, FALSE,
992                           ignore_content_type, FALSE, header_encoding,
993                           outfile, errfile, changelists, ctx, pool);
994 }
995
996 svn_error_t *
997 svn_client_diff3(const apr_array_header_t *options,
998                  const char *path1,
999                  const svn_opt_revision_t *revision1,
1000                  const char *path2,
1001                  const svn_opt_revision_t *revision2,
1002                  svn_boolean_t recurse,
1003                  svn_boolean_t ignore_ancestry,
1004                  svn_boolean_t no_diff_deleted,
1005                  svn_boolean_t ignore_content_type,
1006                  const char *header_encoding,
1007                  apr_file_t *outfile,
1008                  apr_file_t *errfile,
1009                  svn_client_ctx_t *ctx,
1010                  apr_pool_t *pool)
1011 {
1012   return svn_client_diff4(options, path1, revision1, path2,
1013                           revision2, NULL,
1014                           SVN_DEPTH_INFINITY_OR_FILES(recurse),
1015                           ignore_ancestry, no_diff_deleted,
1016                           ignore_content_type, header_encoding,
1017                           outfile, errfile, NULL, ctx, pool);
1018 }
1019
1020 svn_error_t *
1021 svn_client_diff2(const apr_array_header_t *options,
1022                  const char *path1,
1023                  const svn_opt_revision_t *revision1,
1024                  const char *path2,
1025                  const svn_opt_revision_t *revision2,
1026                  svn_boolean_t recurse,
1027                  svn_boolean_t ignore_ancestry,
1028                  svn_boolean_t no_diff_deleted,
1029                  svn_boolean_t ignore_content_type,
1030                  apr_file_t *outfile,
1031                  apr_file_t *errfile,
1032                  svn_client_ctx_t *ctx,
1033                  apr_pool_t *pool)
1034 {
1035   return svn_client_diff3(options, path1, revision1, path2, revision2,
1036                           recurse, ignore_ancestry, no_diff_deleted,
1037                           ignore_content_type, SVN_APR_LOCALE_CHARSET,
1038                           outfile, errfile, ctx, pool);
1039 }
1040
1041 svn_error_t *
1042 svn_client_diff(const apr_array_header_t *options,
1043                 const char *path1,
1044                 const svn_opt_revision_t *revision1,
1045                 const char *path2,
1046                 const svn_opt_revision_t *revision2,
1047                 svn_boolean_t recurse,
1048                 svn_boolean_t ignore_ancestry,
1049                 svn_boolean_t no_diff_deleted,
1050                 apr_file_t *outfile,
1051                 apr_file_t *errfile,
1052                 svn_client_ctx_t *ctx,
1053                 apr_pool_t *pool)
1054 {
1055   return svn_client_diff2(options, path1, revision1, path2, revision2,
1056                           recurse, ignore_ancestry, no_diff_deleted, FALSE,
1057                           outfile, errfile, ctx, pool);
1058 }
1059
1060 svn_error_t *
1061 svn_client_diff_peg5(const apr_array_header_t *diff_options,
1062                      const char *path,
1063                      const svn_opt_revision_t *peg_revision,
1064                      const svn_opt_revision_t *start_revision,
1065                      const svn_opt_revision_t *end_revision,
1066                      const char *relative_to_dir,
1067                      svn_depth_t depth,
1068                      svn_boolean_t ignore_ancestry,
1069                      svn_boolean_t no_diff_deleted,
1070                      svn_boolean_t show_copies_as_adds,
1071                      svn_boolean_t ignore_content_type,
1072                      svn_boolean_t use_git_diff_format,
1073                      const char *header_encoding,
1074                      apr_file_t *outfile,
1075                      apr_file_t *errfile,
1076                      const apr_array_header_t *changelists,
1077                      svn_client_ctx_t *ctx,
1078                      apr_pool_t *pool)
1079 {
1080   svn_stream_t *outstream = svn_stream_from_aprfile2(outfile, TRUE, pool);
1081   svn_stream_t *errstream = svn_stream_from_aprfile2(errfile, TRUE, pool);
1082
1083   return svn_client_diff_peg6(diff_options,
1084                               path,
1085                               peg_revision,
1086                               start_revision,
1087                               end_revision,
1088                               relative_to_dir,
1089                               depth,
1090                               ignore_ancestry,
1091                               FALSE /* no_diff_added */,
1092                               no_diff_deleted,
1093                               show_copies_as_adds,
1094                               ignore_content_type,
1095                               FALSE /* ignore_properties */,
1096                               FALSE /* properties_only */,
1097                               use_git_diff_format,
1098                               header_encoding,
1099                               outstream,
1100                               errstream,
1101                               changelists,
1102                               ctx,
1103                               pool);
1104 }
1105
1106 svn_error_t *
1107 svn_client_diff_peg4(const apr_array_header_t *options,
1108                      const char *path,
1109                      const svn_opt_revision_t *peg_revision,
1110                      const svn_opt_revision_t *start_revision,
1111                      const svn_opt_revision_t *end_revision,
1112                      const char *relative_to_dir,
1113                      svn_depth_t depth,
1114                      svn_boolean_t ignore_ancestry,
1115                      svn_boolean_t no_diff_deleted,
1116                      svn_boolean_t ignore_content_type,
1117                      const char *header_encoding,
1118                      apr_file_t *outfile,
1119                      apr_file_t *errfile,
1120                      const apr_array_header_t *changelists,
1121                      svn_client_ctx_t *ctx,
1122                      apr_pool_t *pool)
1123 {
1124   return svn_client_diff_peg5(options,
1125                               path,
1126                               peg_revision,
1127                               start_revision,
1128                               end_revision,
1129                               relative_to_dir,
1130                               depth,
1131                               ignore_ancestry,
1132                               no_diff_deleted,
1133                               FALSE,
1134                               ignore_content_type,
1135                               FALSE,
1136                               header_encoding,
1137                               outfile,
1138                               errfile,
1139                               changelists,
1140                               ctx,
1141                               pool);
1142 }
1143
1144 svn_error_t *
1145 svn_client_diff_peg3(const apr_array_header_t *options,
1146                      const char *path,
1147                      const svn_opt_revision_t *peg_revision,
1148                      const svn_opt_revision_t *start_revision,
1149                      const svn_opt_revision_t *end_revision,
1150                      svn_boolean_t recurse,
1151                      svn_boolean_t ignore_ancestry,
1152                      svn_boolean_t no_diff_deleted,
1153                      svn_boolean_t ignore_content_type,
1154                      const char *header_encoding,
1155                      apr_file_t *outfile,
1156                      apr_file_t *errfile,
1157                      svn_client_ctx_t *ctx,
1158                      apr_pool_t *pool)
1159 {
1160   return svn_client_diff_peg4(options,
1161                               path,
1162                               peg_revision,
1163                               start_revision,
1164                               end_revision,
1165                               NULL,
1166                               SVN_DEPTH_INFINITY_OR_FILES(recurse),
1167                               ignore_ancestry,
1168                               no_diff_deleted,
1169                               ignore_content_type,
1170                               header_encoding,
1171                               outfile,
1172                               errfile,
1173                               NULL,
1174                               ctx,
1175                               pool);
1176 }
1177
1178 svn_error_t *
1179 svn_client_diff_peg2(const apr_array_header_t *options,
1180                      const char *path,
1181                      const svn_opt_revision_t *peg_revision,
1182                      const svn_opt_revision_t *start_revision,
1183                      const svn_opt_revision_t *end_revision,
1184                      svn_boolean_t recurse,
1185                      svn_boolean_t ignore_ancestry,
1186                      svn_boolean_t no_diff_deleted,
1187                      svn_boolean_t ignore_content_type,
1188                      apr_file_t *outfile,
1189                      apr_file_t *errfile,
1190                      svn_client_ctx_t *ctx,
1191                      apr_pool_t *pool)
1192 {
1193   return svn_client_diff_peg3(options, path, peg_revision, start_revision,
1194                               end_revision,
1195                               SVN_DEPTH_INFINITY_OR_FILES(recurse),
1196                               ignore_ancestry, no_diff_deleted,
1197                               ignore_content_type, SVN_APR_LOCALE_CHARSET,
1198                               outfile, errfile, ctx, pool);
1199 }
1200
1201 svn_error_t *
1202 svn_client_diff_peg(const apr_array_header_t *options,
1203                     const char *path,
1204                     const svn_opt_revision_t *peg_revision,
1205                     const svn_opt_revision_t *start_revision,
1206                     const svn_opt_revision_t *end_revision,
1207                     svn_boolean_t recurse,
1208                     svn_boolean_t ignore_ancestry,
1209                     svn_boolean_t no_diff_deleted,
1210                     apr_file_t *outfile,
1211                     apr_file_t *errfile,
1212                     svn_client_ctx_t *ctx,
1213                     apr_pool_t *pool)
1214 {
1215   return svn_client_diff_peg2(options, path, peg_revision,
1216                               start_revision, end_revision, recurse,
1217                               ignore_ancestry, no_diff_deleted, FALSE,
1218                               outfile, errfile, ctx, pool);
1219 }
1220
1221 svn_error_t *
1222 svn_client_diff_summarize(const char *path1,
1223                           const svn_opt_revision_t *revision1,
1224                           const char *path2,
1225                           const svn_opt_revision_t *revision2,
1226                           svn_boolean_t recurse,
1227                           svn_boolean_t ignore_ancestry,
1228                           svn_client_diff_summarize_func_t summarize_func,
1229                           void *summarize_baton,
1230                           svn_client_ctx_t *ctx,
1231                           apr_pool_t *pool)
1232 {
1233   return svn_client_diff_summarize2(path1, revision1, path2,
1234                                     revision2,
1235                                     SVN_DEPTH_INFINITY_OR_FILES(recurse),
1236                                     ignore_ancestry, NULL, summarize_func,
1237                                     summarize_baton, ctx, pool);
1238 }
1239
1240 svn_error_t *
1241 svn_client_diff_summarize_peg(const char *path,
1242                               const svn_opt_revision_t *peg_revision,
1243                               const svn_opt_revision_t *start_revision,
1244                               const svn_opt_revision_t *end_revision,
1245                               svn_boolean_t recurse,
1246                               svn_boolean_t ignore_ancestry,
1247                               svn_client_diff_summarize_func_t summarize_func,
1248                               void *summarize_baton,
1249                               svn_client_ctx_t *ctx,
1250                               apr_pool_t *pool)
1251 {
1252   return svn_client_diff_summarize_peg2(path, peg_revision,
1253                                         start_revision, end_revision,
1254                                         SVN_DEPTH_INFINITY_OR_FILES(recurse),
1255                                         ignore_ancestry, NULL,
1256                                         summarize_func, summarize_baton,
1257                                         ctx, pool);
1258 }
1259
1260 /*** From export.c ***/
1261 svn_error_t *
1262 svn_client_export4(svn_revnum_t *result_rev,
1263                    const char *from_path_or_url,
1264                    const char *to_path,
1265                    const svn_opt_revision_t *peg_revision,
1266                    const svn_opt_revision_t *revision,
1267                    svn_boolean_t overwrite,
1268                    svn_boolean_t ignore_externals,
1269                    svn_depth_t depth,
1270                    const char *native_eol,
1271                    svn_client_ctx_t *ctx,
1272                    apr_pool_t *pool)
1273 {
1274   return svn_client_export5(result_rev, from_path_or_url, to_path,
1275                             peg_revision, revision, overwrite, ignore_externals,
1276                             FALSE, depth, native_eol, ctx, pool);
1277 }
1278
1279 svn_error_t *
1280 svn_client_export3(svn_revnum_t *result_rev,
1281                    const char *from_path_or_url,
1282                    const char *to_path,
1283                    const svn_opt_revision_t *peg_revision,
1284                    const svn_opt_revision_t *revision,
1285                    svn_boolean_t overwrite,
1286                    svn_boolean_t ignore_externals,
1287                    svn_boolean_t recurse,
1288                    const char *native_eol,
1289                    svn_client_ctx_t *ctx,
1290                    apr_pool_t *pool)
1291 {
1292   return svn_client_export4(result_rev, from_path_or_url, to_path,
1293                             peg_revision, revision, overwrite, ignore_externals,
1294                             SVN_DEPTH_INFINITY_OR_FILES(recurse),
1295                             native_eol, ctx, pool);
1296 }
1297
1298 svn_error_t *
1299 svn_client_export2(svn_revnum_t *result_rev,
1300                    const char *from_path_or_url,
1301                    const char *to_path,
1302                    svn_opt_revision_t *revision,
1303                    svn_boolean_t force,
1304                    const char *native_eol,
1305                    svn_client_ctx_t *ctx,
1306                    apr_pool_t *pool)
1307 {
1308   svn_opt_revision_t peg_revision;
1309
1310   peg_revision.kind = svn_opt_revision_unspecified;
1311
1312   return svn_client_export3(result_rev, from_path_or_url, to_path,
1313                             &peg_revision, revision, force, FALSE, TRUE,
1314                             native_eol, ctx, pool);
1315 }
1316
1317
1318 svn_error_t *
1319 svn_client_export(svn_revnum_t *result_rev,
1320                   const char *from_path_or_url,
1321                   const char *to_path,
1322                   svn_opt_revision_t *revision,
1323                   svn_boolean_t force,
1324                   svn_client_ctx_t *ctx,
1325                   apr_pool_t *pool)
1326 {
1327   return svn_client_export2(result_rev, from_path_or_url, to_path, revision,
1328                             force, NULL, ctx, pool);
1329 }
1330
1331 /*** From list.c ***/
1332
1333 /* Baton for use with wrap_list_func */
1334 struct list_func_wrapper_baton {
1335     void *list_func1_baton;
1336     svn_client_list_func_t list_func1;
1337 };
1338
1339 /* This implements svn_client_list_func2_t */
1340 static svn_error_t *
1341 list_func_wrapper(void *baton,
1342                   const char *path,
1343                   const svn_dirent_t *dirent,
1344                   const svn_lock_t *lock,
1345                   const char *abs_path,
1346                   const char *external_parent_url,
1347                   const char *external_target,
1348                   apr_pool_t *scratch_pool)
1349 {
1350   struct list_func_wrapper_baton *lfwb = baton;
1351
1352   if (lfwb->list_func1)
1353     return lfwb->list_func1(lfwb->list_func1_baton, path, dirent,
1354                            lock, abs_path, scratch_pool);
1355
1356   return SVN_NO_ERROR;
1357 }
1358
1359 /* Helper function for svn_client_list2().  It wraps old format baton
1360    and callback function in list_func_wrapper_baton and
1361    returns new baton and callback to use with svn_client_list3(). */
1362 static void
1363 wrap_list_func(svn_client_list_func2_t *list_func2,
1364                void **list_func2_baton,
1365                svn_client_list_func_t list_func,
1366                void *baton,
1367                apr_pool_t *result_pool)
1368 {
1369   struct list_func_wrapper_baton *lfwb = apr_palloc(result_pool,
1370                                                     sizeof(*lfwb));
1371
1372   /* Set the user provided old format callback in the baton. */
1373   lfwb->list_func1_baton = baton;
1374   lfwb->list_func1 = list_func;
1375
1376   *list_func2_baton = lfwb;
1377   *list_func2 = list_func_wrapper;
1378 }
1379
1380 svn_error_t *
1381 svn_client_list2(const char *path_or_url,
1382                  const svn_opt_revision_t *peg_revision,
1383                  const svn_opt_revision_t *revision,
1384                  svn_depth_t depth,
1385                  apr_uint32_t dirent_fields,
1386                  svn_boolean_t fetch_locks,
1387                  svn_client_list_func_t list_func,
1388                  void *baton,
1389                  svn_client_ctx_t *ctx,
1390                  apr_pool_t *pool)
1391 {
1392   svn_client_list_func2_t list_func2;
1393   void *list_func2_baton;
1394
1395   wrap_list_func(&list_func2, &list_func2_baton, list_func, baton, pool);
1396
1397   return svn_client_list3(path_or_url, peg_revision, revision, depth,
1398                           dirent_fields, fetch_locks,
1399                           FALSE /* include externals */,
1400                           list_func2, list_func2_baton, ctx, pool);
1401 }
1402
1403 svn_error_t *
1404 svn_client_list(const char *path_or_url,
1405                 const svn_opt_revision_t *peg_revision,
1406                 const svn_opt_revision_t *revision,
1407                 svn_boolean_t recurse,
1408                 apr_uint32_t dirent_fields,
1409                 svn_boolean_t fetch_locks,
1410                 svn_client_list_func_t list_func,
1411                 void *baton,
1412                 svn_client_ctx_t *ctx,
1413                 apr_pool_t *pool)
1414 {
1415   return svn_client_list2(path_or_url,
1416                           peg_revision,
1417                           revision,
1418                           SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse),
1419                           dirent_fields,
1420                           fetch_locks,
1421                           list_func,
1422                           baton,
1423                           ctx,
1424                           pool);
1425 }
1426
1427 /* Baton used by compatibility wrapper svn_client_ls3. */
1428 struct ls_baton {
1429   apr_hash_t *dirents;
1430   apr_hash_t *locks;
1431   apr_pool_t *pool;
1432 };
1433
1434 /* This implements svn_client_list_func_t. */
1435 static svn_error_t *
1436 store_dirent(void *baton, const char *path, const svn_dirent_t *dirent,
1437              const svn_lock_t *lock, const char *abs_path, apr_pool_t *pool)
1438 {
1439   struct ls_baton *lb = baton;
1440
1441   /* The dirent is allocated in a temporary pool, so duplicate it into the
1442      correct pool.  Note, however, that the locks are stored in the correct
1443      pool already. */
1444   dirent = svn_dirent_dup(dirent, lb->pool);
1445
1446   /* An empty path means we are called for the target of the operation.
1447      For compatibility, we only store the target if it is a file, and we
1448      store it under the basename of the URL.  Note that this makes it
1449      impossible to differentiate between the target being a directory with a
1450      child with the same basename as the target and the target being a file,
1451      but that's how it was implemented. */
1452   if (path[0] == '\0')
1453     {
1454       if (dirent->kind == svn_node_file)
1455         {
1456           const char *base_name = svn_path_basename(abs_path, lb->pool);
1457           svn_hash_sets(lb->dirents, base_name, dirent);
1458           if (lock)
1459             svn_hash_sets(lb->locks, base_name, lock);
1460         }
1461     }
1462   else
1463     {
1464       path = apr_pstrdup(lb->pool, path);
1465       svn_hash_sets(lb->dirents, path, dirent);
1466       if (lock)
1467         svn_hash_sets(lb->locks, path, lock);
1468     }
1469
1470   return SVN_NO_ERROR;
1471 }
1472
1473 svn_error_t *
1474 svn_client_ls3(apr_hash_t **dirents,
1475                apr_hash_t **locks,
1476                const char *path_or_url,
1477                const svn_opt_revision_t *peg_revision,
1478                const svn_opt_revision_t *revision,
1479                svn_boolean_t recurse,
1480                svn_client_ctx_t *ctx,
1481                apr_pool_t *pool)
1482 {
1483   struct ls_baton lb;
1484
1485   *dirents = lb.dirents = apr_hash_make(pool);
1486   if (locks)
1487     *locks = lb.locks = apr_hash_make(pool);
1488   lb.pool = pool;
1489
1490   return svn_client_list(path_or_url, peg_revision, revision, recurse,
1491                          SVN_DIRENT_ALL, locks != NULL,
1492                          store_dirent, &lb, ctx, pool);
1493 }
1494
1495 svn_error_t *
1496 svn_client_ls2(apr_hash_t **dirents,
1497                const char *path_or_url,
1498                const svn_opt_revision_t *peg_revision,
1499                const svn_opt_revision_t *revision,
1500                svn_boolean_t recurse,
1501                svn_client_ctx_t *ctx,
1502                apr_pool_t *pool)
1503 {
1504
1505   return svn_client_ls3(dirents, NULL, path_or_url, peg_revision,
1506                         revision, recurse, ctx, pool);
1507 }
1508
1509
1510 svn_error_t *
1511 svn_client_ls(apr_hash_t **dirents,
1512               const char *path_or_url,
1513               svn_opt_revision_t *revision,
1514               svn_boolean_t recurse,
1515               svn_client_ctx_t *ctx,
1516               apr_pool_t *pool)
1517 {
1518   return svn_client_ls2(dirents, path_or_url, revision,
1519                         revision, recurse, ctx, pool);
1520 }
1521
1522 /*** From log.c ***/
1523
1524 svn_error_t *
1525 svn_client_log4(const apr_array_header_t *targets,
1526                 const svn_opt_revision_t *peg_revision,
1527                 const svn_opt_revision_t *start,
1528                 const svn_opt_revision_t *end,
1529                 int limit,
1530                 svn_boolean_t discover_changed_paths,
1531                 svn_boolean_t strict_node_history,
1532                 svn_boolean_t include_merged_revisions,
1533                 const apr_array_header_t *revprops,
1534                 svn_log_entry_receiver_t receiver,
1535                 void *receiver_baton,
1536                 svn_client_ctx_t *ctx,
1537                 apr_pool_t *pool)
1538 {
1539   apr_array_header_t *revision_ranges;
1540
1541   revision_ranges = apr_array_make(pool, 1,
1542                                    sizeof(svn_opt_revision_range_t *));
1543   APR_ARRAY_PUSH(revision_ranges, svn_opt_revision_range_t *)
1544     = svn_opt__revision_range_create(start, end, pool);
1545
1546   return svn_client_log5(targets, peg_revision, revision_ranges, limit,
1547                          discover_changed_paths, strict_node_history,
1548                          include_merged_revisions, revprops, receiver,
1549                          receiver_baton, ctx, pool);
1550 }
1551
1552
1553 svn_error_t *
1554 svn_client_log3(const apr_array_header_t *targets,
1555                 const svn_opt_revision_t *peg_revision,
1556                 const svn_opt_revision_t *start,
1557                 const svn_opt_revision_t *end,
1558                 int limit,
1559                 svn_boolean_t discover_changed_paths,
1560                 svn_boolean_t strict_node_history,
1561                 svn_log_message_receiver_t receiver,
1562                 void *receiver_baton,
1563                 svn_client_ctx_t *ctx,
1564                 apr_pool_t *pool)
1565 {
1566   svn_log_entry_receiver_t receiver2;
1567   void *receiver2_baton;
1568
1569   svn_compat_wrap_log_receiver(&receiver2, &receiver2_baton,
1570                                receiver, receiver_baton,
1571                                pool);
1572
1573   return svn_client_log4(targets, peg_revision, start, end, limit,
1574                          discover_changed_paths, strict_node_history, FALSE,
1575                          svn_compat_log_revprops_in(pool),
1576                          receiver2, receiver2_baton, ctx, pool);
1577 }
1578
1579 svn_error_t *
1580 svn_client_log2(const apr_array_header_t *targets,
1581                 const svn_opt_revision_t *start,
1582                 const svn_opt_revision_t *end,
1583                 int limit,
1584                 svn_boolean_t discover_changed_paths,
1585                 svn_boolean_t strict_node_history,
1586                 svn_log_message_receiver_t receiver,
1587                 void *receiver_baton,
1588                 svn_client_ctx_t *ctx,
1589                 apr_pool_t *pool)
1590 {
1591   svn_opt_revision_t peg_revision;
1592   peg_revision.kind = svn_opt_revision_unspecified;
1593   return svn_client_log3(targets, &peg_revision, start, end, limit,
1594                          discover_changed_paths, strict_node_history,
1595                          receiver, receiver_baton, ctx, pool);
1596 }
1597
1598 svn_error_t *
1599 svn_client_log(const apr_array_header_t *targets,
1600                const svn_opt_revision_t *start,
1601                const svn_opt_revision_t *end,
1602                svn_boolean_t discover_changed_paths,
1603                svn_boolean_t strict_node_history,
1604                svn_log_message_receiver_t receiver,
1605                void *receiver_baton,
1606                svn_client_ctx_t *ctx,
1607                apr_pool_t *pool)
1608 {
1609   svn_error_t *err = SVN_NO_ERROR;
1610
1611   err = svn_client_log2(targets, start, end, 0, discover_changed_paths,
1612                         strict_node_history, receiver, receiver_baton, ctx,
1613                         pool);
1614
1615   /* Special case: If there have been no commits, we'll get an error
1616    * for requesting log of a revision higher than 0.  But the
1617    * default behavior of "svn log" is to give revisions HEAD through
1618    * 1, on the assumption that HEAD >= 1.
1619    *
1620    * So if we got that error for that reason, and it looks like the
1621    * user was just depending on the defaults (rather than explicitly
1622    * requesting the log for revision 1), then we don't error.  Instead
1623    * we just invoke the receiver manually on a hand-constructed log
1624    * message for revision 0.
1625    *
1626    * See also http://subversion.tigris.org/issues/show_bug.cgi?id=692.
1627    */
1628   if (err && (err->apr_err == SVN_ERR_FS_NO_SUCH_REVISION)
1629       && (start->kind == svn_opt_revision_head)
1630       && ((end->kind == svn_opt_revision_number)
1631           && (end->value.number == 1)))
1632     {
1633
1634       /* We don't need to check if HEAD is 0, because that must be the case,
1635        * by logical deduction: The revision range specified is HEAD:1.
1636        * HEAD cannot not exist, so the revision to which "no such revision"
1637        * applies is 1. If revision 1 does not exist, then HEAD is 0.
1638        * Hence, we deduce the repository is empty without needing access
1639        * to further information. */
1640
1641       svn_error_clear(err);
1642       err = SVN_NO_ERROR;
1643
1644       /* Log receivers are free to handle revision 0 specially... But
1645          just in case some don't, we make up a message here. */
1646       SVN_ERR(receiver(receiver_baton,
1647                        NULL, 0, "", "", _("No commits in repository"),
1648                        pool));
1649     }
1650
1651   return svn_error_trace(err);
1652 }
1653
1654 /*** From merge.c ***/
1655
1656 svn_error_t *
1657 svn_client_merge4(const char *source1,
1658                   const svn_opt_revision_t *revision1,
1659                   const char *source2,
1660                   const svn_opt_revision_t *revision2,
1661                   const char *target_wcpath,
1662                   svn_depth_t depth,
1663                   svn_boolean_t ignore_ancestry,
1664                   svn_boolean_t force_delete,
1665                   svn_boolean_t record_only,
1666                   svn_boolean_t dry_run,
1667                   svn_boolean_t allow_mixed_rev,
1668                   const apr_array_header_t *merge_options,
1669                   svn_client_ctx_t *ctx,
1670                   apr_pool_t *pool)
1671 {
1672   SVN_ERR(svn_client_merge5(source1, revision1,
1673                             source2, revision2,
1674                             target_wcpath,
1675                             depth,
1676                             ignore_ancestry /*ignore_mergeinfo*/,
1677                             ignore_ancestry /*diff_ignore_ancestry*/,
1678                             force_delete, record_only,
1679                             dry_run, allow_mixed_rev,
1680                             merge_options, ctx, pool));
1681   return SVN_NO_ERROR;
1682 }
1683
1684 svn_error_t *
1685 svn_client_merge3(const char *source1,
1686                   const svn_opt_revision_t *revision1,
1687                   const char *source2,
1688                   const svn_opt_revision_t *revision2,
1689                   const char *target_wcpath,
1690                   svn_depth_t depth,
1691                   svn_boolean_t ignore_ancestry,
1692                   svn_boolean_t force,
1693                   svn_boolean_t record_only,
1694                   svn_boolean_t dry_run,
1695                   const apr_array_header_t *merge_options,
1696                   svn_client_ctx_t *ctx,
1697                   apr_pool_t *pool)
1698 {
1699   return svn_client_merge4(source1, revision1, source2, revision2,
1700                            target_wcpath, depth, ignore_ancestry, force,
1701                            record_only, dry_run, TRUE, merge_options,
1702                            ctx, pool);
1703 }
1704
1705 svn_error_t *
1706 svn_client_merge2(const char *source1,
1707                   const svn_opt_revision_t *revision1,
1708                   const char *source2,
1709                   const svn_opt_revision_t *revision2,
1710                   const char *target_wcpath,
1711                   svn_boolean_t recurse,
1712                   svn_boolean_t ignore_ancestry,
1713                   svn_boolean_t force,
1714                   svn_boolean_t dry_run,
1715                   const apr_array_header_t *merge_options,
1716                   svn_client_ctx_t *ctx,
1717                   apr_pool_t *pool)
1718 {
1719   return svn_client_merge3(source1, revision1, source2, revision2,
1720                            target_wcpath,
1721                            SVN_DEPTH_INFINITY_OR_FILES(recurse),
1722                            ignore_ancestry, force, FALSE, dry_run,
1723                            merge_options, ctx, pool);
1724 }
1725
1726 svn_error_t *
1727 svn_client_merge(const char *source1,
1728                  const svn_opt_revision_t *revision1,
1729                  const char *source2,
1730                  const svn_opt_revision_t *revision2,
1731                  const char *target_wcpath,
1732                  svn_boolean_t recurse,
1733                  svn_boolean_t ignore_ancestry,
1734                  svn_boolean_t force,
1735                  svn_boolean_t dry_run,
1736                  svn_client_ctx_t *ctx,
1737                  apr_pool_t *pool)
1738 {
1739   return svn_client_merge2(source1, revision1, source2, revision2,
1740                            target_wcpath, recurse, ignore_ancestry, force,
1741                            dry_run, NULL, ctx, pool);
1742 }
1743
1744 svn_error_t *
1745 svn_client_merge_peg4(const char *source_path_or_url,
1746                       const apr_array_header_t *ranges_to_merge,
1747                       const svn_opt_revision_t *source_peg_revision,
1748                       const char *target_wcpath,
1749                       svn_depth_t depth,
1750                       svn_boolean_t ignore_ancestry,
1751                       svn_boolean_t force_delete,
1752                       svn_boolean_t record_only,
1753                       svn_boolean_t dry_run,
1754                       svn_boolean_t allow_mixed_rev,
1755                       const apr_array_header_t *merge_options,
1756                       svn_client_ctx_t *ctx,
1757                       apr_pool_t *pool)
1758 {
1759   SVN_ERR(svn_client_merge_peg5(source_path_or_url,
1760                                 ranges_to_merge,
1761                                 source_peg_revision,
1762                                 target_wcpath,
1763                                 depth,
1764                                 ignore_ancestry /*ignore_mergeinfo*/,
1765                                 ignore_ancestry /*diff_ignore_ancestry*/,
1766                                 force_delete, record_only,
1767                                 dry_run, allow_mixed_rev,
1768                                 merge_options, ctx, pool));
1769   return SVN_NO_ERROR;
1770 }
1771
1772 svn_error_t *
1773 svn_client_merge_peg3(const char *source,
1774                       const apr_array_header_t *ranges_to_merge,
1775                       const svn_opt_revision_t *peg_revision,
1776                       const char *target_wcpath,
1777                       svn_depth_t depth,
1778                       svn_boolean_t ignore_ancestry,
1779                       svn_boolean_t force,
1780                       svn_boolean_t record_only,
1781                       svn_boolean_t dry_run,
1782                       const apr_array_header_t *merge_options,
1783                       svn_client_ctx_t *ctx,
1784                       apr_pool_t *pool)
1785 {
1786   return svn_client_merge_peg4(source, ranges_to_merge, peg_revision,
1787                                target_wcpath, depth, ignore_ancestry, force,
1788                                record_only, dry_run, TRUE, merge_options,
1789                                ctx, pool);
1790 }
1791
1792 svn_error_t *
1793 svn_client_merge_peg2(const char *source,
1794                       const svn_opt_revision_t *revision1,
1795                       const svn_opt_revision_t *revision2,
1796                       const svn_opt_revision_t *peg_revision,
1797                       const char *target_wcpath,
1798                       svn_boolean_t recurse,
1799                       svn_boolean_t ignore_ancestry,
1800                       svn_boolean_t force,
1801                       svn_boolean_t dry_run,
1802                       const apr_array_header_t *merge_options,
1803                       svn_client_ctx_t *ctx,
1804                       apr_pool_t *pool)
1805 {
1806   apr_array_header_t *ranges_to_merge =
1807     apr_array_make(pool, 1, sizeof(svn_opt_revision_range_t *));
1808
1809   APR_ARRAY_PUSH(ranges_to_merge, svn_opt_revision_range_t *)
1810     = svn_opt__revision_range_create(revision1, revision2, pool);
1811   return svn_client_merge_peg3(source, ranges_to_merge,
1812                                peg_revision,
1813                                target_wcpath,
1814                                SVN_DEPTH_INFINITY_OR_FILES(recurse),
1815                                ignore_ancestry, force, FALSE, dry_run,
1816                                merge_options, ctx, pool);
1817 }
1818
1819 svn_error_t *
1820 svn_client_merge_peg(const char *source,
1821                      const svn_opt_revision_t *revision1,
1822                      const svn_opt_revision_t *revision2,
1823                      const svn_opt_revision_t *peg_revision,
1824                      const char *target_wcpath,
1825                      svn_boolean_t recurse,
1826                      svn_boolean_t ignore_ancestry,
1827                      svn_boolean_t force,
1828                      svn_boolean_t dry_run,
1829                      svn_client_ctx_t *ctx,
1830                      apr_pool_t *pool)
1831 {
1832   return svn_client_merge_peg2(source, revision1, revision2, peg_revision,
1833                                target_wcpath, recurse, ignore_ancestry, force,
1834                                dry_run, NULL, ctx, pool);
1835 }
1836
1837 /*** From prop_commands.c ***/
1838 svn_error_t *
1839 svn_client_propset3(svn_commit_info_t **commit_info_p,
1840                     const char *propname,
1841                     const svn_string_t *propval,
1842                     const char *target,
1843                     svn_depth_t depth,
1844                     svn_boolean_t skip_checks,
1845                     svn_revnum_t base_revision_for_url,
1846                     const apr_array_header_t *changelists,
1847                     const apr_hash_t *revprop_table,
1848                     svn_client_ctx_t *ctx,
1849                     apr_pool_t *pool)
1850 {
1851   if (svn_path_is_url(target))
1852     {
1853       struct capture_baton_t cb;
1854
1855       cb.info = commit_info_p;
1856       cb.pool = pool;
1857
1858       SVN_ERR(svn_client_propset_remote(propname, propval, target, skip_checks,
1859                                         base_revision_for_url, revprop_table,
1860                                         capture_commit_info, &cb, ctx, pool));
1861     }
1862   else
1863     {
1864       apr_array_header_t *targets = apr_array_make(pool, 1,
1865                                                    sizeof(const char *));
1866
1867       APR_ARRAY_PUSH(targets, const char *) = target;
1868       SVN_ERR(svn_client_propset_local(propname, propval, targets, depth,
1869                                        skip_checks, changelists, ctx, pool));
1870     }
1871
1872   return SVN_NO_ERROR;
1873 }
1874
1875 svn_error_t *
1876 svn_client_propset2(const char *propname,
1877                     const svn_string_t *propval,
1878                     const char *target,
1879                     svn_boolean_t recurse,
1880                     svn_boolean_t skip_checks,
1881                     svn_client_ctx_t *ctx,
1882                     apr_pool_t *pool)
1883 {
1884   return svn_client_propset3(NULL, propname, propval, target,
1885                              SVN_DEPTH_INFINITY_OR_EMPTY(recurse),
1886                              skip_checks, SVN_INVALID_REVNUM,
1887                              NULL, NULL, ctx, pool);
1888 }
1889
1890
1891 svn_error_t *
1892 svn_client_propset(const char *propname,
1893                    const svn_string_t *propval,
1894                    const char *target,
1895                    svn_boolean_t recurse,
1896                    apr_pool_t *pool)
1897 {
1898   svn_client_ctx_t *ctx;
1899
1900   SVN_ERR(svn_client_create_context(&ctx, pool));
1901
1902   return svn_client_propset2(propname, propval, target, recurse, FALSE,
1903                              ctx, pool);
1904 }
1905
1906 svn_error_t *
1907 svn_client_revprop_set(const char *propname,
1908                        const svn_string_t *propval,
1909                        const char *URL,
1910                        const svn_opt_revision_t *revision,
1911                        svn_revnum_t *set_rev,
1912                        svn_boolean_t force,
1913                        svn_client_ctx_t *ctx,
1914                        apr_pool_t *pool)
1915 {
1916   return svn_client_revprop_set2(propname, propval, NULL, URL,
1917                                  revision, set_rev, force, ctx, pool);
1918
1919 }
1920
1921 svn_error_t *
1922 svn_client_propget4(apr_hash_t **props,
1923                     const char *propname,
1924                     const char *target,
1925                     const svn_opt_revision_t *peg_revision,
1926                     const svn_opt_revision_t *revision,
1927                     svn_revnum_t *actual_revnum,
1928                     svn_depth_t depth,
1929                     const apr_array_header_t *changelists,
1930                     svn_client_ctx_t *ctx,
1931                     apr_pool_t *result_pool,
1932                     apr_pool_t *scratch_pool)
1933 {
1934   return svn_error_trace(svn_client_propget5(props, NULL, propname, target,
1935                                              peg_revision, revision,
1936                                              actual_revnum, depth,
1937                                              changelists, ctx,
1938                                              result_pool, scratch_pool));
1939 }
1940
1941 svn_error_t *
1942 svn_client_propget3(apr_hash_t **props,
1943                     const char *propname,
1944                     const char *path_or_url,
1945                     const svn_opt_revision_t *peg_revision,
1946                     const svn_opt_revision_t *revision,
1947                     svn_revnum_t *actual_revnum,
1948                     svn_depth_t depth,
1949                     const apr_array_header_t *changelists,
1950                     svn_client_ctx_t *ctx,
1951                     apr_pool_t *pool)
1952 {
1953   const char *target;
1954   apr_hash_t *temp_props;
1955   svn_error_t *err;
1956
1957   if (svn_path_is_url(path_or_url))
1958     target = path_or_url;
1959   else
1960     SVN_ERR(svn_dirent_get_absolute(&target, path_or_url, pool));
1961
1962   err = svn_client_propget4(&temp_props, propname, target,
1963                             peg_revision, revision, actual_revnum,
1964                             depth, changelists, ctx, pool, pool);
1965
1966   if (err && err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE)
1967     {
1968       err->apr_err = SVN_ERR_ENTRY_NOT_FOUND;
1969       return svn_error_trace(err);
1970     }
1971   else
1972     SVN_ERR(err);
1973
1974   if (actual_revnum
1975         && !svn_path_is_url(path_or_url)
1976         && !SVN_IS_VALID_REVNUM(*actual_revnum))
1977     {
1978       /* Get the actual_revnum; added nodes have no revision yet, and old
1979        * callers expected the mock-up revision of 0. */
1980       svn_boolean_t added;
1981
1982       SVN_ERR(svn_wc__node_is_added(&added, ctx->wc_ctx, target, pool));
1983       if (added)
1984         *actual_revnum = 0;
1985     }
1986
1987   /* We may need to fix up our hash keys for legacy callers. */
1988   if (!svn_path_is_url(path_or_url) && strcmp(target, path_or_url) != 0)
1989     {
1990       apr_hash_index_t *hi;
1991
1992       *props = apr_hash_make(pool);
1993       for (hi = apr_hash_first(pool, temp_props); hi;
1994             hi = apr_hash_next(hi))
1995         {
1996           const char *abspath = apr_hash_this_key(hi);
1997           svn_string_t *value = apr_hash_this_val(hi);
1998           const char *relpath = svn_dirent_join(path_or_url,
1999                                      svn_dirent_skip_ancestor(target, abspath),
2000                                      pool);
2001
2002           svn_hash_sets(*props, relpath, value);
2003         }
2004     }
2005   else
2006     *props = temp_props;
2007
2008   return SVN_NO_ERROR;
2009 }
2010
2011 svn_error_t *
2012 svn_client_propget2(apr_hash_t **props,
2013                     const char *propname,
2014                     const char *target,
2015                     const svn_opt_revision_t *peg_revision,
2016                     const svn_opt_revision_t *revision,
2017                     svn_boolean_t recurse,
2018                     svn_client_ctx_t *ctx,
2019                     apr_pool_t *pool)
2020 {
2021   return svn_client_propget3(props,
2022                              propname,
2023                              target,
2024                              peg_revision,
2025                              revision,
2026                              NULL,
2027                              SVN_DEPTH_INFINITY_OR_EMPTY(recurse),
2028                              NULL,
2029                              ctx,
2030                              pool);
2031 }
2032
2033 svn_error_t *
2034 svn_client_propget(apr_hash_t **props,
2035                    const char *propname,
2036                    const char *target,
2037                    const svn_opt_revision_t *revision,
2038                    svn_boolean_t recurse,
2039                    svn_client_ctx_t *ctx,
2040                    apr_pool_t *pool)
2041 {
2042   return svn_client_propget2(props, propname, target, revision, revision,
2043                              recurse, ctx, pool);
2044 }
2045
2046
2047 /* Duplicate a HASH containing (char * -> svn_string_t *) key/value
2048    pairs using POOL. */
2049 static apr_hash_t *
2050 string_hash_dup(apr_hash_t *hash, apr_pool_t *pool)
2051 {
2052   apr_hash_index_t *hi;
2053   apr_hash_t *new_hash = apr_hash_make(pool);
2054
2055   for (hi = apr_hash_first(pool, hash); hi; hi = apr_hash_next(hi))
2056     {
2057       const char *key = apr_pstrdup(pool, apr_hash_this_key(hi));
2058       apr_ssize_t klen = apr_hash_this_key_len(hi);
2059       svn_string_t *val = svn_string_dup(apr_hash_this_val(hi), pool);
2060
2061       apr_hash_set(new_hash, key, klen, val);
2062     }
2063   return new_hash;
2064 }
2065
2066 svn_client_proplist_item_t *
2067 svn_client_proplist_item_dup(const svn_client_proplist_item_t *item,
2068                              apr_pool_t * pool)
2069 {
2070   svn_client_proplist_item_t *new_item = apr_pcalloc(pool, sizeof(*new_item));
2071
2072   if (item->node_name)
2073     new_item->node_name = svn_stringbuf_dup(item->node_name, pool);
2074
2075   if (item->prop_hash)
2076     new_item->prop_hash = string_hash_dup(item->prop_hash, pool);
2077
2078   return new_item;
2079 }
2080
2081 /* Baton for use with wrap_proplist_receiver */
2082 struct proplist_receiver_wrapper_baton {
2083   void *baton;
2084   svn_proplist_receiver_t receiver;
2085 };
2086
2087 /* This implements svn_client_proplist_receiver2_t */
2088 static svn_error_t *
2089 proplist_wrapper_receiver(void *baton,
2090                           const char *path,
2091                           apr_hash_t *prop_hash,
2092                           apr_array_header_t *inherited_props,
2093                           apr_pool_t *pool)
2094 {
2095   struct proplist_receiver_wrapper_baton *plrwb = baton;
2096
2097   if (plrwb->receiver)
2098     return plrwb->receiver(plrwb->baton, path, prop_hash, pool);
2099
2100   return SVN_NO_ERROR;
2101 }
2102
2103 static void
2104 wrap_proplist_receiver(svn_proplist_receiver2_t *receiver2,
2105                        void **receiver2_baton,
2106                        svn_proplist_receiver_t receiver,
2107                        void *receiver_baton,
2108                        apr_pool_t *pool)
2109 {
2110   struct proplist_receiver_wrapper_baton *plrwb = apr_palloc(pool,
2111                                                              sizeof(*plrwb));
2112
2113   /* Set the user provided old format callback in the baton. */
2114   plrwb->baton = receiver_baton;
2115   plrwb->receiver = receiver;
2116
2117   *receiver2_baton = plrwb;
2118   *receiver2 = proplist_wrapper_receiver;
2119 }
2120
2121 svn_error_t *
2122 svn_client_proplist3(const char *target,
2123                      const svn_opt_revision_t *peg_revision,
2124                      const svn_opt_revision_t *revision,
2125                      svn_depth_t depth,
2126                      const apr_array_header_t *changelists,
2127                      svn_proplist_receiver_t receiver,
2128                      void *receiver_baton,
2129                      svn_client_ctx_t *ctx,
2130                      apr_pool_t *pool)
2131 {
2132
2133   svn_proplist_receiver2_t receiver2;
2134   void *receiver2_baton;
2135
2136   wrap_proplist_receiver(&receiver2, &receiver2_baton, receiver, receiver_baton,
2137                          pool);
2138
2139   return svn_error_trace(svn_client_proplist4(target, peg_revision, revision,
2140                                               depth, changelists, FALSE,
2141                                               receiver2, receiver2_baton,
2142                                               ctx, pool));
2143 }
2144
2145 /* Receiver baton used by proplist2() */
2146 struct proplist_receiver_baton {
2147   apr_array_header_t *props;
2148   apr_pool_t *pool;
2149 };
2150
2151 /* Receiver function used by proplist2(). */
2152 static svn_error_t *
2153 proplist_receiver_cb(void *baton,
2154                      const char *path,
2155                      apr_hash_t *prop_hash,
2156                      apr_pool_t *pool)
2157 {
2158   struct proplist_receiver_baton *pl_baton =
2159     (struct proplist_receiver_baton *) baton;
2160   svn_client_proplist_item_t *tmp_item = apr_palloc(pool, sizeof(*tmp_item));
2161   svn_client_proplist_item_t *item;
2162
2163   /* Because the pool passed to the receiver function is likely to be a
2164      temporary pool of some kind, we need to make copies of *path and
2165      *prop_hash in the pool provided by the baton. */
2166   tmp_item->node_name = svn_stringbuf_create(path, pl_baton->pool);
2167   tmp_item->prop_hash = prop_hash;
2168
2169   item = svn_client_proplist_item_dup(tmp_item, pl_baton->pool);
2170
2171   APR_ARRAY_PUSH(pl_baton->props, const svn_client_proplist_item_t *) = item;
2172
2173   return SVN_NO_ERROR;
2174 }
2175
2176 svn_error_t *
2177 svn_client_proplist2(apr_array_header_t **props,
2178                      const char *target,
2179                      const svn_opt_revision_t *peg_revision,
2180                      const svn_opt_revision_t *revision,
2181                      svn_boolean_t recurse,
2182                      svn_client_ctx_t *ctx,
2183                      apr_pool_t *pool)
2184 {
2185   struct proplist_receiver_baton pl_baton;
2186
2187   *props = apr_array_make(pool, 5, sizeof(svn_client_proplist_item_t *));
2188   pl_baton.props = *props;
2189   pl_baton.pool = pool;
2190
2191   return svn_client_proplist3(target, peg_revision, revision,
2192                               SVN_DEPTH_INFINITY_OR_EMPTY(recurse), NULL,
2193                               proplist_receiver_cb, &pl_baton, ctx, pool);
2194 }
2195
2196
2197 svn_error_t *
2198 svn_client_proplist(apr_array_header_t **props,
2199                     const char *target,
2200                     const svn_opt_revision_t *revision,
2201                     svn_boolean_t recurse,
2202                     svn_client_ctx_t *ctx,
2203                     apr_pool_t *pool)
2204 {
2205   return svn_client_proplist2(props, target, revision, revision,
2206                               recurse, ctx, pool);
2207 }
2208
2209 /*** From status.c ***/
2210
2211 svn_error_t *
2212 svn_client_status5(svn_revnum_t *result_rev,
2213                    svn_client_ctx_t *ctx,
2214                    const char *path,
2215                    const svn_opt_revision_t *revision,
2216                    svn_depth_t depth,
2217                    svn_boolean_t get_all,
2218                    svn_boolean_t update,
2219                    svn_boolean_t no_ignore,
2220                    svn_boolean_t ignore_externals,
2221                    svn_boolean_t depth_as_sticky,
2222                    const apr_array_header_t *changelists,
2223                    svn_client_status_func_t status_func,
2224                    void *status_baton,
2225                    apr_pool_t *scratch_pool)
2226 {
2227   return svn_client_status6(result_rev, ctx, path, revision, depth,
2228                             get_all, update, TRUE, no_ignore,
2229                             ignore_externals, depth_as_sticky, changelists,
2230                             status_func, status_baton, scratch_pool);
2231 }
2232
2233 struct status4_wrapper_baton
2234 {
2235   svn_wc_context_t *wc_ctx;
2236   svn_wc_status_func3_t old_func;
2237   void *old_baton;
2238 };
2239
2240 /* Implements svn_client_status_func_t */
2241 static svn_error_t *
2242 status4_wrapper_func(void *baton,
2243                      const char *path,
2244                      const svn_client_status_t *status,
2245                      apr_pool_t *scratch_pool)
2246 {
2247   struct status4_wrapper_baton *swb = baton;
2248   svn_wc_status2_t *dup;
2249   const char *local_abspath;
2250   const svn_wc_status3_t *wc_status = status->backwards_compatibility_baton;
2251
2252   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
2253   SVN_ERR(svn_wc__status2_from_3(&dup, wc_status, swb->wc_ctx,
2254                                  local_abspath, scratch_pool,
2255                                  scratch_pool));
2256
2257   return (*swb->old_func)(swb->old_baton, path, dup, scratch_pool);
2258 }
2259
2260 svn_error_t *
2261 svn_client_status4(svn_revnum_t *result_rev,
2262                    const char *path,
2263                    const svn_opt_revision_t *revision,
2264                    svn_wc_status_func3_t status_func,
2265                    void *status_baton,
2266                    svn_depth_t depth,
2267                    svn_boolean_t get_all,
2268                    svn_boolean_t update,
2269                    svn_boolean_t no_ignore,
2270                    svn_boolean_t ignore_externals,
2271                    const apr_array_header_t *changelists,
2272                    svn_client_ctx_t *ctx,
2273                    apr_pool_t *pool)
2274 {
2275   struct status4_wrapper_baton swb;
2276
2277   swb.wc_ctx = ctx->wc_ctx;
2278   swb.old_func = status_func;
2279   swb.old_baton = status_baton;
2280
2281   return svn_client_status5(result_rev, ctx, path, revision, depth, get_all,
2282                             update, no_ignore, ignore_externals, TRUE,
2283                             changelists, status4_wrapper_func, &swb, pool);
2284 }
2285
2286 struct status3_wrapper_baton
2287 {
2288   svn_wc_status_func2_t old_func;
2289   void *old_baton;
2290 };
2291
2292 static svn_error_t *
2293 status3_wrapper_func(void *baton,
2294                      const char *path,
2295                      svn_wc_status2_t *status,
2296                      apr_pool_t *pool)
2297 {
2298   struct status3_wrapper_baton *swb = baton;
2299
2300   swb->old_func(swb->old_baton, path, status);
2301   return SVN_NO_ERROR;
2302 }
2303
2304 svn_error_t *
2305 svn_client_status3(svn_revnum_t *result_rev,
2306                    const char *path,
2307                    const svn_opt_revision_t *revision,
2308                    svn_wc_status_func2_t status_func,
2309                    void *status_baton,
2310                    svn_depth_t depth,
2311                    svn_boolean_t get_all,
2312                    svn_boolean_t update,
2313                    svn_boolean_t no_ignore,
2314                    svn_boolean_t ignore_externals,
2315                    const apr_array_header_t *changelists,
2316                    svn_client_ctx_t *ctx,
2317                    apr_pool_t *pool)
2318 {
2319   struct status3_wrapper_baton swb = { 0 };
2320   swb.old_func = status_func;
2321   swb.old_baton = status_baton;
2322   return svn_client_status4(result_rev, path, revision, status3_wrapper_func,
2323                             &swb, depth, get_all, update, no_ignore,
2324                             ignore_externals, changelists, ctx, pool);
2325 }
2326
2327 svn_error_t *
2328 svn_client_status2(svn_revnum_t *result_rev,
2329                    const char *path,
2330                    const svn_opt_revision_t *revision,
2331                    svn_wc_status_func2_t status_func,
2332                    void *status_baton,
2333                    svn_boolean_t recurse,
2334                    svn_boolean_t get_all,
2335                    svn_boolean_t update,
2336                    svn_boolean_t no_ignore,
2337                    svn_boolean_t ignore_externals,
2338                    svn_client_ctx_t *ctx,
2339                    apr_pool_t *pool)
2340 {
2341   return svn_client_status3(result_rev, path, revision,
2342                             status_func, status_baton,
2343                             SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse),
2344                             get_all, update, no_ignore, ignore_externals, NULL,
2345                             ctx, pool);
2346 }
2347
2348
2349 /* Baton for old_status_func_cb; does what you think it does. */
2350 struct old_status_func_cb_baton
2351 {
2352   svn_wc_status_func_t original_func;
2353   void *original_baton;
2354 };
2355
2356 /* Help svn_client_status() accept an old-style status func and baton,
2357    by wrapping them before passing along to svn_client_status2().
2358
2359    This implements the 'svn_wc_status_func2_t' function type. */
2360 static void old_status_func_cb(void *baton,
2361                                const char *path,
2362                                svn_wc_status2_t *status)
2363 {
2364   struct old_status_func_cb_baton *b = baton;
2365   svn_wc_status_t *stat = (svn_wc_status_t *) status;
2366
2367   b->original_func(b->original_baton, path, stat);
2368 }
2369
2370
2371 svn_error_t *
2372 svn_client_status(svn_revnum_t *result_rev,
2373                   const char *path,
2374                   svn_opt_revision_t *revision,
2375                   svn_wc_status_func_t status_func,
2376                   void *status_baton,
2377                   svn_boolean_t recurse,
2378                   svn_boolean_t get_all,
2379                   svn_boolean_t update,
2380                   svn_boolean_t no_ignore,
2381                   svn_client_ctx_t *ctx,
2382                   apr_pool_t *pool)
2383 {
2384   struct old_status_func_cb_baton *b = apr_pcalloc(pool, sizeof(*b));
2385   b->original_func = status_func;
2386   b->original_baton = status_baton;
2387
2388   return svn_client_status2(result_rev, path, revision,
2389                             old_status_func_cb, b,
2390                             recurse, get_all, update, no_ignore, FALSE,
2391                             ctx, pool);
2392 }
2393
2394 /*** From update.c ***/
2395 svn_error_t *
2396 svn_client_update3(apr_array_header_t **result_revs,
2397                    const apr_array_header_t *paths,
2398                    const svn_opt_revision_t *revision,
2399                    svn_depth_t depth,
2400                    svn_boolean_t depth_is_sticky,
2401                    svn_boolean_t ignore_externals,
2402                    svn_boolean_t allow_unver_obstructions,
2403                    svn_client_ctx_t *ctx,
2404                    apr_pool_t *pool)
2405 {
2406   return svn_client_update4(result_revs, paths, revision,
2407                             depth, depth_is_sticky, ignore_externals,
2408                             allow_unver_obstructions, TRUE, FALSE,
2409                             ctx, pool);
2410 }
2411
2412 svn_error_t *
2413 svn_client_update2(apr_array_header_t **result_revs,
2414                    const apr_array_header_t *paths,
2415                    const svn_opt_revision_t *revision,
2416                    svn_boolean_t recurse,
2417                    svn_boolean_t ignore_externals,
2418                    svn_client_ctx_t *ctx,
2419                    apr_pool_t *pool)
2420 {
2421   return svn_client_update3(result_revs, paths, revision,
2422                             SVN_DEPTH_INFINITY_OR_FILES(recurse), FALSE,
2423                             ignore_externals, FALSE, ctx, pool);
2424 }
2425
2426 svn_error_t *
2427 svn_client_update(svn_revnum_t *result_rev,
2428                   const char *path,
2429                   const svn_opt_revision_t *revision,
2430                   svn_boolean_t recurse,
2431                   svn_client_ctx_t *ctx,
2432                   apr_pool_t *pool)
2433 {
2434   apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(const char *));
2435   apr_array_header_t *result_revs;
2436
2437   APR_ARRAY_PUSH(paths, const char *) = path;
2438
2439   SVN_ERR(svn_client_update2(&result_revs, paths, revision, recurse, FALSE,
2440                              ctx, pool));
2441
2442   *result_rev = APR_ARRAY_IDX(result_revs, 0, svn_revnum_t);
2443
2444   return SVN_NO_ERROR;
2445 }
2446
2447 /*** From switch.c ***/
2448 svn_error_t *
2449 svn_client_switch2(svn_revnum_t *result_rev,
2450                    const char *path,
2451                    const char *switch_url,
2452                    const svn_opt_revision_t *peg_revision,
2453                    const svn_opt_revision_t *revision,
2454                    svn_depth_t depth,
2455                    svn_boolean_t depth_is_sticky,
2456                    svn_boolean_t ignore_externals,
2457                    svn_boolean_t allow_unver_obstructions,
2458                    svn_client_ctx_t *ctx,
2459                    apr_pool_t *pool)
2460 {
2461   return svn_client_switch3(result_rev, path, switch_url, peg_revision,
2462                             revision, depth, depth_is_sticky, ignore_externals,
2463                             allow_unver_obstructions,
2464                             TRUE /* ignore_ancestry */,
2465                             ctx, pool);
2466 }
2467
2468 svn_error_t *
2469 svn_client_switch(svn_revnum_t *result_rev,
2470                   const char *path,
2471                   const char *switch_url,
2472                   const svn_opt_revision_t *revision,
2473                   svn_boolean_t recurse,
2474                   svn_client_ctx_t *ctx,
2475                   apr_pool_t *pool)
2476 {
2477   svn_opt_revision_t peg_revision;
2478   peg_revision.kind = svn_opt_revision_unspecified;
2479   return svn_client_switch2(result_rev, path, switch_url,
2480                             &peg_revision, revision,
2481                             SVN_DEPTH_INFINITY_OR_FILES(recurse),
2482                             FALSE, FALSE, FALSE, ctx, pool);
2483 }
2484
2485 /*** From cat.c ***/
2486 svn_error_t *
2487 svn_client_cat2(svn_stream_t *out,
2488                 const char *path_or_url,
2489                 const svn_opt_revision_t *peg_revision,
2490                 const svn_opt_revision_t *revision,
2491                 svn_client_ctx_t *ctx,
2492                 apr_pool_t *pool)
2493 {
2494   return svn_client_cat3(NULL /* props */,
2495                          out, path_or_url, peg_revision, revision,
2496                          TRUE /* expand_keywords */,
2497                          ctx, pool, pool);
2498 }
2499
2500
2501 svn_error_t *
2502 svn_client_cat(svn_stream_t *out,
2503                const char *path_or_url,
2504                const svn_opt_revision_t *revision,
2505                svn_client_ctx_t *ctx,
2506                apr_pool_t *pool)
2507 {
2508   return svn_client_cat2(out, path_or_url, revision, revision,
2509                          ctx, pool);
2510 }
2511
2512 /*** From checkout.c ***/
2513 svn_error_t *
2514 svn_client_checkout2(svn_revnum_t *result_rev,
2515                      const char *URL,
2516                      const char *path,
2517                      const svn_opt_revision_t *peg_revision,
2518                      const svn_opt_revision_t *revision,
2519                      svn_boolean_t recurse,
2520                      svn_boolean_t ignore_externals,
2521                      svn_client_ctx_t *ctx,
2522                      apr_pool_t *pool)
2523 {
2524   return svn_error_trace(svn_client_checkout3(result_rev, URL, path,
2525                                         peg_revision, revision,
2526                                         SVN_DEPTH_INFINITY_OR_FILES(recurse),
2527                                         ignore_externals, FALSE, ctx, pool));
2528 }
2529
2530 svn_error_t *
2531 svn_client_checkout(svn_revnum_t *result_rev,
2532                     const char *URL,
2533                     const char *path,
2534                     const svn_opt_revision_t *revision,
2535                     svn_boolean_t recurse,
2536                     svn_client_ctx_t *ctx,
2537                     apr_pool_t *pool)
2538 {
2539   svn_opt_revision_t peg_revision;
2540
2541   peg_revision.kind = svn_opt_revision_unspecified;
2542
2543   return svn_error_trace(svn_client_checkout2(result_rev, URL, path,
2544                                               &peg_revision, revision, recurse,
2545                                               FALSE, ctx, pool));
2546 }
2547
2548 /*** From info.c ***/
2549
2550 svn_error_t *
2551 svn_client_info3(const char *abspath_or_url,
2552                  const svn_opt_revision_t *peg_revision,
2553                  const svn_opt_revision_t *revision,
2554                  svn_depth_t depth,
2555                  svn_boolean_t fetch_excluded,
2556                  svn_boolean_t fetch_actual_only,
2557                  const apr_array_header_t *changelists,
2558                  svn_client_info_receiver2_t receiver,
2559                  void *receiver_baton,
2560                  svn_client_ctx_t *ctx,
2561                  apr_pool_t *pool)
2562 {
2563   return svn_error_trace(
2564             svn_client_info4(abspath_or_url,
2565                              peg_revision,
2566                              revision,
2567                              depth,
2568                              fetch_excluded,
2569                              fetch_actual_only,
2570                              FALSE /* include_externals */,
2571                              changelists,
2572                              receiver, receiver_baton,
2573                              ctx, pool));
2574 }
2575
2576 svn_info_t *
2577 svn_info_dup(const svn_info_t *info, apr_pool_t *pool)
2578 {
2579   svn_info_t *dupinfo = apr_palloc(pool, sizeof(*dupinfo));
2580
2581   /* Perform a trivial copy ... */
2582   *dupinfo = *info;
2583
2584   /* ...and then re-copy stuff that needs to be duped into our pool. */
2585   if (info->URL)
2586     dupinfo->URL = apr_pstrdup(pool, info->URL);
2587   if (info->repos_root_URL)
2588     dupinfo->repos_root_URL = apr_pstrdup(pool, info->repos_root_URL);
2589   if (info->repos_UUID)
2590     dupinfo->repos_UUID = apr_pstrdup(pool, info->repos_UUID);
2591   if (info->last_changed_author)
2592     dupinfo->last_changed_author = apr_pstrdup(pool,
2593                                                info->last_changed_author);
2594   if (info->lock)
2595     dupinfo->lock = svn_lock_dup(info->lock, pool);
2596   if (info->copyfrom_url)
2597     dupinfo->copyfrom_url = apr_pstrdup(pool, info->copyfrom_url);
2598   if (info->checksum)
2599     dupinfo->checksum = apr_pstrdup(pool, info->checksum);
2600   if (info->conflict_old)
2601     dupinfo->conflict_old = apr_pstrdup(pool, info->conflict_old);
2602   if (info->conflict_new)
2603     dupinfo->conflict_new = apr_pstrdup(pool, info->conflict_new);
2604   if (info->conflict_wrk)
2605     dupinfo->conflict_wrk = apr_pstrdup(pool, info->conflict_wrk);
2606   if (info->prejfile)
2607     dupinfo->prejfile = apr_pstrdup(pool, info->prejfile);
2608
2609   return dupinfo;
2610 }
2611
2612 /* Convert an svn_client_info2_t to an svn_info_t, doing shallow copies. */
2613 static svn_error_t *
2614 info_from_info2(svn_info_t **new_info,
2615                 svn_wc_context_t *wc_ctx,
2616                 const svn_client_info2_t *info2,
2617                 apr_pool_t *pool)
2618 {
2619   svn_info_t *info = apr_pcalloc(pool, sizeof(*info));
2620
2621   info->URL                 = info2->URL;
2622   /* Goofy backward compat handling for added nodes. */
2623   if (SVN_IS_VALID_REVNUM(info2->rev))
2624     info->rev               = info2->rev;
2625   else
2626     info->rev               = 0;
2627
2628   info->kind                = info2->kind;
2629   info->repos_root_URL      = info2->repos_root_URL;
2630   info->repos_UUID          = info2->repos_UUID;
2631   info->last_changed_rev    = info2->last_changed_rev;
2632   info->last_changed_date   = info2->last_changed_date;
2633   info->last_changed_author = info2->last_changed_author;
2634
2635   /* Stupid old structure has a non-const LOCK member. Sigh.  */
2636   info->lock                = (svn_lock_t *)info2->lock;
2637
2638   info->size64              = info2->size;
2639   if (info2->size == SVN_INVALID_FILESIZE)
2640     info->size               = SVN_INFO_SIZE_UNKNOWN;
2641   else if (((svn_filesize_t)(apr_size_t)info->size64) == info->size64)
2642     info->size               = (apr_size_t)info->size64;
2643   else /* >= 4GB */
2644     info->size               = SVN_INFO_SIZE_UNKNOWN;
2645
2646   if (info2->wc_info)
2647     {
2648       info->has_wc_info         = TRUE;
2649       info->schedule            = info2->wc_info->schedule;
2650       info->copyfrom_url        = info2->wc_info->copyfrom_url;
2651       info->copyfrom_rev        = info2->wc_info->copyfrom_rev;
2652       info->text_time           = info2->wc_info->recorded_time;
2653       info->prop_time           = 0;
2654       if (info2->wc_info->checksum
2655             && info2->wc_info->checksum->kind == svn_checksum_md5)
2656         info->checksum          = svn_checksum_to_cstring(
2657                                         info2->wc_info->checksum, pool);
2658       else
2659         info->checksum          = NULL;
2660       info->changelist          = info2->wc_info->changelist;
2661       info->depth               = info2->wc_info->depth;
2662
2663       if (info->depth == svn_depth_unknown && info->kind == svn_node_file)
2664         info->depth = svn_depth_infinity;
2665
2666       info->working_size64      = info2->wc_info->recorded_size;
2667       if (((svn_filesize_t)(apr_size_t)info->working_size64) == info->working_size64)
2668         info->working_size       = (apr_size_t)info->working_size64;
2669       else /* >= 4GB */
2670         info->working_size       = SVN_INFO_SIZE_UNKNOWN;
2671     }
2672   else
2673     {
2674       info->has_wc_info           = FALSE;
2675       info->working_size          = SVN_INFO_SIZE_UNKNOWN;
2676       info->working_size64        = SVN_INVALID_FILESIZE;
2677       info->depth                 = svn_depth_unknown;
2678     }
2679
2680   /* Populate conflict fields. */
2681   if (info2->wc_info && info2->wc_info->conflicts)
2682     {
2683       int i;
2684
2685       for (i = 0; i < info2->wc_info->conflicts->nelts; i++)
2686         {
2687           const svn_wc_conflict_description2_t *conflict
2688                               = APR_ARRAY_IDX(info2->wc_info->conflicts, i,
2689                                     const svn_wc_conflict_description2_t *);
2690
2691           /* ### Not really sure what we should do if we get multiple
2692              ### conflicts of the same type. */
2693           switch (conflict->kind)
2694             {
2695               case svn_wc_conflict_kind_tree:
2696                 info->tree_conflict = svn_wc__cd2_to_cd(conflict, pool);
2697                 break;
2698
2699               case svn_wc_conflict_kind_text:
2700                 info->conflict_old = conflict->base_abspath;
2701                 info->conflict_new = conflict->my_abspath;
2702                 info->conflict_wrk = conflict->their_abspath;
2703                 break;
2704
2705               case svn_wc_conflict_kind_property:
2706                 info->prejfile = conflict->their_abspath;
2707                 break;
2708             }
2709         }
2710     }
2711
2712   if (info2->wc_info && info2->wc_info->checksum)
2713     {
2714       const svn_checksum_t *md5_checksum;
2715
2716       SVN_ERR(svn_wc__node_get_md5_from_sha1(&md5_checksum,
2717                                              wc_ctx,
2718                                              info2->wc_info->wcroot_abspath,
2719                                              info2->wc_info->checksum,
2720                                              pool, pool));
2721
2722       info->checksum = svn_checksum_to_cstring(md5_checksum, pool);
2723     }
2724
2725   *new_info = info;
2726   return SVN_NO_ERROR;
2727 }
2728
2729 struct info_to_relpath_baton
2730 {
2731   const char *anchor_abspath;
2732   const char *anchor_relpath;
2733   svn_info_receiver_t info_receiver;
2734   void *info_baton;
2735   svn_wc_context_t *wc_ctx;
2736 };
2737
2738 static svn_error_t *
2739 info_receiver_relpath_wrapper(void *baton,
2740                               const char *abspath_or_url,
2741                               const svn_client_info2_t *info2,
2742                               apr_pool_t *scratch_pool)
2743 {
2744   struct info_to_relpath_baton *rb = baton;
2745   const char *path = abspath_or_url;
2746   svn_info_t *info;
2747
2748   if (rb->anchor_relpath &&
2749       svn_dirent_is_ancestor(rb->anchor_abspath, abspath_or_url))
2750     {
2751       path = svn_dirent_join(rb->anchor_relpath,
2752                              svn_dirent_skip_ancestor(rb->anchor_abspath,
2753                                                       abspath_or_url),
2754                              scratch_pool);
2755     }
2756
2757   SVN_ERR(info_from_info2(&info, rb->wc_ctx, info2, scratch_pool));
2758
2759   SVN_ERR(rb->info_receiver(rb->info_baton,
2760                             path,
2761                             info,
2762                             scratch_pool));
2763
2764   return SVN_NO_ERROR;
2765 }
2766
2767 svn_error_t *
2768 svn_client_info2(const char *path_or_url,
2769                  const svn_opt_revision_t *peg_revision,
2770                  const svn_opt_revision_t *revision,
2771                  svn_info_receiver_t receiver,
2772                  void *receiver_baton,
2773                  svn_depth_t depth,
2774                  const apr_array_header_t *changelists,
2775                  svn_client_ctx_t *ctx,
2776                  apr_pool_t *pool)
2777 {
2778   struct info_to_relpath_baton rb;
2779   const char *abspath_or_url = path_or_url;
2780
2781   rb.anchor_relpath = NULL;
2782   rb.info_receiver = receiver;
2783   rb.info_baton = receiver_baton;
2784   rb.wc_ctx = ctx->wc_ctx;
2785
2786   if (!svn_path_is_url(path_or_url))
2787     {
2788       SVN_ERR(svn_dirent_get_absolute(&abspath_or_url, path_or_url, pool));
2789       rb.anchor_abspath = abspath_or_url;
2790       rb.anchor_relpath = path_or_url;
2791     }
2792
2793   SVN_ERR(svn_client_info3(abspath_or_url,
2794                            peg_revision,
2795                            revision,
2796                            depth,
2797                            FALSE, TRUE,
2798                            changelists,
2799                            info_receiver_relpath_wrapper,
2800                            &rb,
2801                            ctx,
2802                            pool));
2803
2804   return SVN_NO_ERROR;
2805 }
2806
2807 svn_error_t *
2808 svn_client_info(const char *path_or_url,
2809                 const svn_opt_revision_t *peg_revision,
2810                 const svn_opt_revision_t *revision,
2811                 svn_info_receiver_t receiver,
2812                 void *receiver_baton,
2813                 svn_boolean_t recurse,
2814                 svn_client_ctx_t *ctx,
2815                 apr_pool_t *pool)
2816 {
2817   return svn_client_info2(path_or_url, peg_revision, revision,
2818                           receiver, receiver_baton,
2819                           SVN_DEPTH_INFINITY_OR_EMPTY(recurse),
2820                           NULL, ctx, pool);
2821 }
2822
2823 /*** From resolved.c ***/
2824 svn_error_t *
2825 svn_client_resolved(const char *path,
2826                     svn_boolean_t recursive,
2827                     svn_client_ctx_t *ctx,
2828                     apr_pool_t *pool)
2829 {
2830   svn_depth_t depth = SVN_DEPTH_INFINITY_OR_EMPTY(recursive);
2831   return svn_client_resolve(path, depth,
2832                             svn_wc_conflict_choose_merged, ctx, pool);
2833 }
2834 /*** From revert.c ***/
2835 svn_error_t *
2836 svn_client_revert2(const apr_array_header_t *paths,
2837                    svn_depth_t depth,
2838                    const apr_array_header_t *changelists,
2839                    svn_client_ctx_t *ctx,
2840                    apr_pool_t *pool)
2841 {
2842   return svn_error_trace(svn_client_revert3(paths,
2843                                             depth,
2844                                             changelists,
2845                                             FALSE /* clear_changelists */,
2846                                             FALSE /* metadata_only */,
2847                                             ctx,
2848                                             pool));
2849 }
2850
2851 svn_error_t *
2852 svn_client_revert(const apr_array_header_t *paths,
2853                   svn_boolean_t recursive,
2854                   svn_client_ctx_t *ctx,
2855                   apr_pool_t *pool)
2856 {
2857   return svn_client_revert2(paths, SVN_DEPTH_INFINITY_OR_EMPTY(recursive),
2858                             NULL, ctx, pool);
2859 }
2860
2861 /*** From ra.c ***/
2862 svn_error_t *
2863 svn_client_open_ra_session(svn_ra_session_t **session,
2864                            const char *url,
2865                            svn_client_ctx_t *ctx,
2866                            apr_pool_t *pool)
2867 {
2868   return svn_error_trace(
2869              svn_client_open_ra_session2(session, url,
2870                                          NULL, ctx,
2871                                          pool, pool));
2872 }
2873
2874 svn_error_t *
2875 svn_client_uuid_from_url(const char **uuid,
2876                          const char *url,
2877                          svn_client_ctx_t *ctx,
2878                          apr_pool_t *pool)
2879 {
2880   svn_error_t *err;
2881   apr_pool_t *subpool = svn_pool_create(pool);
2882
2883   err = svn_client_get_repos_root(NULL, uuid, url,
2884                                   ctx, pool, subpool);
2885   /* destroy the RA session */
2886   svn_pool_destroy(subpool);
2887
2888   return svn_error_trace(err);
2889 }
2890
2891 svn_error_t *
2892 svn_client_uuid_from_path2(const char **uuid,
2893                            const char *local_abspath,
2894                            svn_client_ctx_t *ctx,
2895                            apr_pool_t *result_pool,
2896                            apr_pool_t *scratch_pool)
2897 {
2898   return svn_error_trace(
2899       svn_client_get_repos_root(NULL, uuid,
2900                                 local_abspath, ctx,
2901                                 result_pool, scratch_pool));
2902 }
2903
2904 svn_error_t *
2905 svn_client_uuid_from_path(const char **uuid,
2906                           const char *path,
2907                           svn_wc_adm_access_t *adm_access,
2908                           svn_client_ctx_t *ctx,
2909                           apr_pool_t *pool)
2910 {
2911   const char *local_abspath;
2912
2913   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
2914   return svn_error_trace(
2915     svn_client_uuid_from_path2(uuid, local_abspath, ctx, pool, pool));
2916 }
2917
2918 /*** From url.c ***/
2919 svn_error_t *
2920 svn_client_root_url_from_path(const char **url,
2921                               const char *path_or_url,
2922                               svn_client_ctx_t *ctx,
2923                               apr_pool_t *pool)
2924 {
2925   apr_pool_t *subpool = svn_pool_create(pool);
2926   svn_error_t *err;
2927   if (!svn_path_is_url(path_or_url))
2928     SVN_ERR(svn_dirent_get_absolute(&path_or_url, path_or_url, pool));
2929
2930   err = svn_client_get_repos_root(url, NULL, path_or_url,
2931                                   ctx, pool, subpool);
2932
2933   /* close ra session */
2934   svn_pool_destroy(subpool);
2935   return svn_error_trace(err);
2936 }
2937
2938 svn_error_t *
2939 svn_client_url_from_path(const char **url,
2940                          const char *path_or_url,
2941                          apr_pool_t *pool)
2942 {
2943   svn_client_ctx_t *ctx;
2944
2945   SVN_ERR(svn_client_create_context(&ctx, pool));
2946
2947   return svn_client_url_from_path2(url, path_or_url, ctx, pool, pool);
2948 }
2949
2950 /*** From mergeinfo.c ***/
2951 svn_error_t *
2952 svn_client_mergeinfo_log(svn_boolean_t finding_merged,
2953                          const char *target_path_or_url,
2954                          const svn_opt_revision_t *target_peg_revision,
2955                          const char *source_path_or_url,
2956                          const svn_opt_revision_t *source_peg_revision,
2957                          svn_log_entry_receiver_t receiver,
2958                          void *receiver_baton,
2959                          svn_boolean_t discover_changed_paths,
2960                          svn_depth_t depth,
2961                          const apr_array_header_t *revprops,
2962                          svn_client_ctx_t *ctx,
2963                          apr_pool_t *scratch_pool)
2964 {
2965   svn_opt_revision_t start_revision, end_revision;
2966
2967   start_revision.kind = svn_opt_revision_unspecified;
2968   end_revision.kind = svn_opt_revision_unspecified;
2969
2970   return svn_client_mergeinfo_log2(finding_merged,
2971                                    target_path_or_url, target_peg_revision,
2972                                    source_path_or_url, source_peg_revision,
2973                                    &start_revision, &end_revision,
2974                                    receiver, receiver_baton,
2975                                    discover_changed_paths, depth, revprops,
2976                                    ctx, scratch_pool);
2977 }
2978
2979 svn_error_t *
2980 svn_client_mergeinfo_log_merged(const char *path_or_url,
2981                                 const svn_opt_revision_t *peg_revision,
2982                                 const char *merge_source_path_or_url,
2983                                 const svn_opt_revision_t *src_peg_revision,
2984                                 svn_log_entry_receiver_t log_receiver,
2985                                 void *log_receiver_baton,
2986                                 svn_boolean_t discover_changed_paths,
2987                                 const apr_array_header_t *revprops,
2988                                 svn_client_ctx_t *ctx,
2989                                 apr_pool_t *pool)
2990 {
2991   return svn_client_mergeinfo_log(TRUE, path_or_url, peg_revision,
2992                                   merge_source_path_or_url,
2993                                   src_peg_revision,
2994                                   log_receiver, log_receiver_baton,
2995                                   discover_changed_paths,
2996                                   svn_depth_empty, revprops, ctx,
2997                                   pool);
2998 }
2999
3000 svn_error_t *
3001 svn_client_mergeinfo_log_eligible(const char *path_or_url,
3002                                   const svn_opt_revision_t *peg_revision,
3003                                   const char *merge_source_path_or_url,
3004                                   const svn_opt_revision_t *src_peg_revision,
3005                                   svn_log_entry_receiver_t log_receiver,
3006                                   void *log_receiver_baton,
3007                                   svn_boolean_t discover_changed_paths,
3008                                   const apr_array_header_t *revprops,
3009                                   svn_client_ctx_t *ctx,
3010                                   apr_pool_t *pool)
3011 {
3012   return svn_client_mergeinfo_log(FALSE, path_or_url, peg_revision,
3013                                   merge_source_path_or_url,
3014                                   src_peg_revision,
3015                                   log_receiver, log_receiver_baton,
3016                                   discover_changed_paths,
3017                                   svn_depth_empty, revprops, ctx,
3018                                   pool);
3019 }
3020
3021 /*** From relocate.c ***/
3022 svn_error_t *
3023 svn_client_relocate(const char *path,
3024                     const char *from_prefix,
3025                     const char *to_prefix,
3026                     svn_boolean_t recurse,
3027                     svn_client_ctx_t *ctx,
3028                     apr_pool_t *pool)
3029 {
3030   if (! recurse)
3031     SVN_ERR(svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
3032                              _("Non-recursive relocation not supported")));
3033   return svn_client_relocate2(path, from_prefix, to_prefix, TRUE, ctx, pool);
3034 }
3035
3036 /*** From util.c ***/
3037 svn_error_t *
3038 svn_client_commit_item_create(const svn_client_commit_item3_t **item,
3039                               apr_pool_t *pool)
3040 {
3041   *item = svn_client_commit_item3_create(pool);
3042   return SVN_NO_ERROR;
3043 }
3044
3045 svn_client_commit_item2_t *
3046 svn_client_commit_item2_dup(const svn_client_commit_item2_t *item,
3047                             apr_pool_t *pool)
3048 {
3049   svn_client_commit_item2_t *new_item = apr_palloc(pool, sizeof(*new_item));
3050
3051   *new_item = *item;
3052
3053   if (new_item->path)
3054     new_item->path = apr_pstrdup(pool, new_item->path);
3055
3056   if (new_item->url)
3057     new_item->url = apr_pstrdup(pool, new_item->url);
3058
3059   if (new_item->copyfrom_url)
3060     new_item->copyfrom_url = apr_pstrdup(pool, new_item->copyfrom_url);
3061
3062   if (new_item->wcprop_changes)
3063     new_item->wcprop_changes = svn_prop_array_dup(new_item->wcprop_changes,
3064                                                   pool);
3065
3066   return new_item;
3067 }
3068
3069 svn_error_t *
3070 svn_client_cleanup(const char *path,
3071                    svn_client_ctx_t *ctx,
3072                    apr_pool_t *scratch_pool)
3073 {
3074   const char *local_abspath;
3075
3076   if (svn_path_is_url(path))
3077     return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
3078                              _("'%s' is not a local path"), path);
3079
3080   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
3081
3082   return svn_error_trace(svn_client_cleanup2(local_abspath,
3083                                              TRUE /* break_locks */,
3084                                              TRUE /* fix_recorded_timestamps */,
3085                                              TRUE /* clear_dav_cache */,
3086                                              TRUE /* vacuum_pristines */,
3087                                              FALSE /* include_externals */,
3088                                              ctx, scratch_pool));
3089 }