]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/subversion/subversion/libsvn_client/deprecated.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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_copy5(svn_commit_info_t **commit_info_p,
631                  const apr_array_header_t *sources,
632                  const char *dst_path,
633                  svn_boolean_t copy_as_child,
634                  svn_boolean_t make_parents,
635                  svn_boolean_t ignore_externals,
636                  const apr_hash_t *revprop_table,
637                  svn_client_ctx_t *ctx,
638                  apr_pool_t *pool)
639 {
640   struct capture_baton_t cb;
641
642   cb.info = commit_info_p;
643   cb.pool = pool;
644
645   return svn_client_copy6(sources, dst_path, copy_as_child, make_parents,
646                           ignore_externals, revprop_table,
647                           capture_commit_info, &cb, ctx, pool);
648 }
649
650 svn_error_t *
651 svn_client_copy4(svn_commit_info_t **commit_info_p,
652                  const apr_array_header_t *sources,
653                  const char *dst_path,
654                  svn_boolean_t copy_as_child,
655                  svn_boolean_t make_parents,
656                  const apr_hash_t *revprop_table,
657                  svn_client_ctx_t *ctx,
658                  apr_pool_t *pool)
659 {
660   return svn_client_copy5(commit_info_p, sources, dst_path, copy_as_child,
661                           make_parents, FALSE, revprop_table, ctx, pool);
662 }
663
664 svn_error_t *
665 svn_client_copy3(svn_commit_info_t **commit_info_p,
666                  const char *src_path,
667                  const svn_opt_revision_t *src_revision,
668                  const char *dst_path,
669                  svn_client_ctx_t *ctx,
670                  apr_pool_t *pool)
671 {
672   apr_array_header_t *sources = apr_array_make(pool, 1,
673                                   sizeof(const svn_client_copy_source_t *));
674   svn_client_copy_source_t copy_source;
675
676   copy_source.path = src_path;
677   copy_source.revision = src_revision;
678   copy_source.peg_revision = src_revision;
679
680   APR_ARRAY_PUSH(sources, const svn_client_copy_source_t *) = &copy_source;
681
682   return svn_client_copy4(commit_info_p, sources, dst_path, FALSE, FALSE,
683                           NULL, ctx, pool);
684 }
685
686 svn_error_t *
687 svn_client_copy2(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   svn_error_t *err;
695
696   err = svn_client_copy3(commit_info_p, src_path, src_revision,
697                          dst_path, ctx, pool);
698
699   /* If the target exists, try to copy the source as a child of the target.
700      This will obviously fail if target is not a directory, but that's exactly
701      what we want. */
702   if (err && (err->apr_err == SVN_ERR_ENTRY_EXISTS
703               || err->apr_err == SVN_ERR_FS_ALREADY_EXISTS))
704     {
705       const char *src_basename = svn_path_basename(src_path, pool);
706
707       svn_error_clear(err);
708
709       return svn_client_copy3(commit_info_p, src_path, src_revision,
710                               svn_path_join(dst_path, src_basename, pool),
711                               ctx, pool);
712     }
713
714   return svn_error_trace(err);
715 }
716
717 svn_error_t *
718 svn_client_copy(svn_client_commit_info_t **commit_info_p,
719                 const char *src_path,
720                 const svn_opt_revision_t *src_revision,
721                 const char *dst_path,
722                 svn_client_ctx_t *ctx,
723                 apr_pool_t *pool)
724 {
725   svn_commit_info_t *commit_info = NULL;
726   svn_error_t *err;
727
728   err = svn_client_copy2(&commit_info, src_path, src_revision, dst_path,
729                          ctx, pool);
730   /* These structs have the same layout for the common fields. */
731   *commit_info_p = (svn_client_commit_info_t *) commit_info;
732   return svn_error_trace(err);
733 }
734
735 svn_error_t *
736 svn_client_move6(const apr_array_header_t *src_paths,
737                  const char *dst_path,
738                  svn_boolean_t move_as_child,
739                  svn_boolean_t make_parents,
740                  const apr_hash_t *revprop_table,
741                  svn_commit_callback2_t commit_callback,
742                  void *commit_baton,
743                  svn_client_ctx_t *ctx,
744                  apr_pool_t *pool)
745 {
746   return svn_error_trace(svn_client_move7(src_paths, dst_path,
747                                           move_as_child, make_parents,
748                                           TRUE /* allow_mixed_revisions */,
749                                           FALSE /* metadata_only */,
750                                           revprop_table,
751                                           commit_callback, commit_baton,
752                                           ctx, pool));
753 }
754
755 svn_error_t *
756 svn_client_move5(svn_commit_info_t **commit_info_p,
757                  const apr_array_header_t *src_paths,
758                  const char *dst_path,
759                  svn_boolean_t force,
760                  svn_boolean_t move_as_child,
761                  svn_boolean_t make_parents,
762                  const apr_hash_t *revprop_table,
763                  svn_client_ctx_t *ctx,
764                  apr_pool_t *pool)
765 {
766   struct capture_baton_t cb;
767
768   cb.info = commit_info_p;
769   cb.pool = pool;
770
771   return svn_client_move6(src_paths, dst_path, move_as_child,
772                           make_parents, revprop_table,
773                           capture_commit_info, &cb, ctx, pool);
774 }
775
776 svn_error_t *
777 svn_client_move4(svn_commit_info_t **commit_info_p,
778                  const char *src_path,
779                  const char *dst_path,
780                  svn_boolean_t force,
781                  svn_client_ctx_t *ctx,
782                  apr_pool_t *pool)
783 {
784   apr_array_header_t *src_paths =
785     apr_array_make(pool, 1, sizeof(const char *));
786   APR_ARRAY_PUSH(src_paths, const char *) = src_path;
787
788
789   return svn_client_move5(commit_info_p, src_paths, dst_path, force, FALSE,
790                           FALSE, NULL, ctx, pool);
791 }
792
793 svn_error_t *
794 svn_client_move3(svn_commit_info_t **commit_info_p,
795                  const char *src_path,
796                  const char *dst_path,
797                  svn_boolean_t force,
798                  svn_client_ctx_t *ctx,
799                  apr_pool_t *pool)
800 {
801   svn_error_t *err;
802
803   err = svn_client_move4(commit_info_p, src_path, dst_path, force, ctx, pool);
804
805   /* If the target exists, try to move the source as a child of the target.
806      This will obviously fail if target is not a directory, but that's exactly
807      what we want. */
808   if (err && (err->apr_err == SVN_ERR_ENTRY_EXISTS
809               || err->apr_err == SVN_ERR_FS_ALREADY_EXISTS))
810     {
811       const char *src_basename = svn_path_basename(src_path, pool);
812
813       svn_error_clear(err);
814
815       return svn_client_move4(commit_info_p, src_path,
816                               svn_path_join(dst_path, src_basename, pool),
817                               force, ctx, pool);
818     }
819
820   return svn_error_trace(err);
821 }
822
823 svn_error_t *
824 svn_client_move2(svn_client_commit_info_t **commit_info_p,
825                  const char *src_path,
826                  const char *dst_path,
827                  svn_boolean_t force,
828                  svn_client_ctx_t *ctx,
829                  apr_pool_t *pool)
830 {
831   svn_commit_info_t *commit_info = NULL;
832   svn_error_t *err;
833
834   err = svn_client_move3(&commit_info, src_path, dst_path, force, ctx, pool);
835   /* These structs have the same layout for the common fields. */
836   *commit_info_p = (svn_client_commit_info_t *) commit_info;
837   return svn_error_trace(err);
838 }
839
840
841 svn_error_t *
842 svn_client_move(svn_client_commit_info_t **commit_info_p,
843                 const char *src_path,
844                 const svn_opt_revision_t *src_revision,
845                 const char *dst_path,
846                 svn_boolean_t force,
847                 svn_client_ctx_t *ctx,
848                 apr_pool_t *pool)
849 {
850   /* It doesn't make sense to specify revisions in a move. */
851
852   /* ### todo: this check could fail wrongly.  For example,
853      someone could pass in an svn_opt_revision_number that just
854      happens to be the HEAD.  It's fair enough to punt then, IMHO,
855      and just demand that the user not specify a revision at all;
856      beats mucking up this function with RA calls and such. */
857   if (src_revision->kind != svn_opt_revision_unspecified
858       && src_revision->kind != svn_opt_revision_head)
859     {
860       return svn_error_create
861         (SVN_ERR_UNSUPPORTED_FEATURE, NULL,
862          _("Cannot specify revisions (except HEAD) with move operations"));
863     }
864
865   return svn_client_move2(commit_info_p, src_path, dst_path, force, ctx, pool);
866 }
867
868 /*** From delete.c ***/
869 svn_error_t *
870 svn_client_delete3(svn_commit_info_t **commit_info_p,
871                    const apr_array_header_t *paths,
872                    svn_boolean_t force,
873                    svn_boolean_t keep_local,
874                    const apr_hash_t *revprop_table,
875                    svn_client_ctx_t *ctx,
876                    apr_pool_t *pool)
877 {
878   struct capture_baton_t cb;
879
880   cb.info = commit_info_p;
881   cb.pool = pool;
882
883   return svn_client_delete4(paths, force, keep_local, revprop_table,
884                             capture_commit_info, &cb, ctx, pool);
885 }
886
887 svn_error_t *
888 svn_client_delete2(svn_commit_info_t **commit_info_p,
889                    const apr_array_header_t *paths,
890                    svn_boolean_t force,
891                    svn_client_ctx_t *ctx,
892                    apr_pool_t *pool)
893 {
894   return svn_client_delete3(commit_info_p, paths, force, FALSE, NULL,
895                             ctx, pool);
896 }
897
898 svn_error_t *
899 svn_client_delete(svn_client_commit_info_t **commit_info_p,
900                   const apr_array_header_t *paths,
901                   svn_boolean_t force,
902                   svn_client_ctx_t *ctx,
903                   apr_pool_t *pool)
904 {
905   svn_commit_info_t *commit_info = NULL;
906   svn_error_t *err = NULL;
907
908   err = svn_client_delete2(&commit_info, paths, force, ctx, pool);
909   /* These structs have the same layout for the common fields. */
910   *commit_info_p = (svn_client_commit_info_t *) commit_info;
911   return svn_error_trace(err);
912 }
913
914 /*** From diff.c ***/
915
916 svn_error_t *
917 svn_client_diff5(const apr_array_header_t *diff_options,
918                  const char *path1,
919                  const svn_opt_revision_t *revision1,
920                  const char *path2,
921                  const svn_opt_revision_t *revision2,
922                  const char *relative_to_dir,
923                  svn_depth_t depth,
924                  svn_boolean_t ignore_ancestry,
925                  svn_boolean_t no_diff_deleted,
926                  svn_boolean_t show_copies_as_adds,
927                  svn_boolean_t ignore_content_type,
928                  svn_boolean_t use_git_diff_format,
929                  const char *header_encoding,
930                  apr_file_t *outfile,
931                  apr_file_t *errfile,
932                  const apr_array_header_t *changelists,
933                  svn_client_ctx_t *ctx,
934                  apr_pool_t *pool)
935 {
936   svn_stream_t *outstream = svn_stream_from_aprfile2(outfile, TRUE, pool);
937   svn_stream_t *errstream = svn_stream_from_aprfile2(errfile, TRUE, pool);
938
939   return svn_client_diff6(diff_options, path1, revision1, path2,
940                           revision2, relative_to_dir, depth,
941                           ignore_ancestry, FALSE /* no_diff_added */,
942                           no_diff_deleted, show_copies_as_adds,
943                           ignore_content_type, FALSE /* ignore_properties */,
944                           FALSE /* properties_only */, use_git_diff_format,
945                           header_encoding,
946                           outstream, errstream, changelists, ctx, pool);
947 }
948
949 svn_error_t *
950 svn_client_diff4(const apr_array_header_t *options,
951                  const char *path1,
952                  const svn_opt_revision_t *revision1,
953                  const char *path2,
954                  const svn_opt_revision_t *revision2,
955                  const char *relative_to_dir,
956                  svn_depth_t depth,
957                  svn_boolean_t ignore_ancestry,
958                  svn_boolean_t no_diff_deleted,
959                  svn_boolean_t ignore_content_type,
960                  const char *header_encoding,
961                  apr_file_t *outfile,
962                  apr_file_t *errfile,
963                  const apr_array_header_t *changelists,
964                  svn_client_ctx_t *ctx,
965                  apr_pool_t *pool)
966 {
967   return svn_client_diff5(options, path1, revision1, path2,
968                           revision2, relative_to_dir, depth,
969                           ignore_ancestry, no_diff_deleted, FALSE,
970                           ignore_content_type, FALSE, header_encoding,
971                           outfile, errfile, changelists, ctx, pool);
972 }
973
974 svn_error_t *
975 svn_client_diff3(const apr_array_header_t *options,
976                  const char *path1,
977                  const svn_opt_revision_t *revision1,
978                  const char *path2,
979                  const svn_opt_revision_t *revision2,
980                  svn_boolean_t recurse,
981                  svn_boolean_t ignore_ancestry,
982                  svn_boolean_t no_diff_deleted,
983                  svn_boolean_t ignore_content_type,
984                  const char *header_encoding,
985                  apr_file_t *outfile,
986                  apr_file_t *errfile,
987                  svn_client_ctx_t *ctx,
988                  apr_pool_t *pool)
989 {
990   return svn_client_diff4(options, path1, revision1, path2,
991                           revision2, NULL,
992                           SVN_DEPTH_INFINITY_OR_FILES(recurse),
993                           ignore_ancestry, no_diff_deleted,
994                           ignore_content_type, header_encoding,
995                           outfile, errfile, NULL, ctx, pool);
996 }
997
998 svn_error_t *
999 svn_client_diff2(const apr_array_header_t *options,
1000                  const char *path1,
1001                  const svn_opt_revision_t *revision1,
1002                  const char *path2,
1003                  const svn_opt_revision_t *revision2,
1004                  svn_boolean_t recurse,
1005                  svn_boolean_t ignore_ancestry,
1006                  svn_boolean_t no_diff_deleted,
1007                  svn_boolean_t ignore_content_type,
1008                  apr_file_t *outfile,
1009                  apr_file_t *errfile,
1010                  svn_client_ctx_t *ctx,
1011                  apr_pool_t *pool)
1012 {
1013   return svn_client_diff3(options, path1, revision1, path2, revision2,
1014                           recurse, ignore_ancestry, no_diff_deleted,
1015                           ignore_content_type, SVN_APR_LOCALE_CHARSET,
1016                           outfile, errfile, ctx, pool);
1017 }
1018
1019 svn_error_t *
1020 svn_client_diff(const apr_array_header_t *options,
1021                 const char *path1,
1022                 const svn_opt_revision_t *revision1,
1023                 const char *path2,
1024                 const svn_opt_revision_t *revision2,
1025                 svn_boolean_t recurse,
1026                 svn_boolean_t ignore_ancestry,
1027                 svn_boolean_t no_diff_deleted,
1028                 apr_file_t *outfile,
1029                 apr_file_t *errfile,
1030                 svn_client_ctx_t *ctx,
1031                 apr_pool_t *pool)
1032 {
1033   return svn_client_diff2(options, path1, revision1, path2, revision2,
1034                           recurse, ignore_ancestry, no_diff_deleted, FALSE,
1035                           outfile, errfile, ctx, pool);
1036 }
1037
1038 svn_error_t *
1039 svn_client_diff_peg5(const apr_array_header_t *diff_options,
1040                      const char *path,
1041                      const svn_opt_revision_t *peg_revision,
1042                      const svn_opt_revision_t *start_revision,
1043                      const svn_opt_revision_t *end_revision,
1044                      const char *relative_to_dir,
1045                      svn_depth_t depth,
1046                      svn_boolean_t ignore_ancestry,
1047                      svn_boolean_t no_diff_deleted,
1048                      svn_boolean_t show_copies_as_adds,
1049                      svn_boolean_t ignore_content_type,
1050                      svn_boolean_t use_git_diff_format,
1051                      const char *header_encoding,
1052                      apr_file_t *outfile,
1053                      apr_file_t *errfile,
1054                      const apr_array_header_t *changelists,
1055                      svn_client_ctx_t *ctx,
1056                      apr_pool_t *pool)
1057 {
1058   svn_stream_t *outstream = svn_stream_from_aprfile2(outfile, TRUE, pool);
1059   svn_stream_t *errstream = svn_stream_from_aprfile2(errfile, TRUE, pool);
1060
1061   return svn_client_diff_peg6(diff_options,
1062                               path,
1063                               peg_revision,
1064                               start_revision,
1065                               end_revision,
1066                               relative_to_dir,
1067                               depth,
1068                               ignore_ancestry,
1069                               FALSE /* no_diff_added */,
1070                               no_diff_deleted,
1071                               show_copies_as_adds,
1072                               ignore_content_type,
1073                               FALSE /* ignore_properties */,
1074                               FALSE /* properties_only */,
1075                               use_git_diff_format,
1076                               header_encoding,
1077                               outstream,
1078                               errstream,
1079                               changelists,
1080                               ctx,
1081                               pool);
1082 }
1083
1084 svn_error_t *
1085 svn_client_diff_peg4(const apr_array_header_t *options,
1086                      const char *path,
1087                      const svn_opt_revision_t *peg_revision,
1088                      const svn_opt_revision_t *start_revision,
1089                      const svn_opt_revision_t *end_revision,
1090                      const char *relative_to_dir,
1091                      svn_depth_t depth,
1092                      svn_boolean_t ignore_ancestry,
1093                      svn_boolean_t no_diff_deleted,
1094                      svn_boolean_t ignore_content_type,
1095                      const char *header_encoding,
1096                      apr_file_t *outfile,
1097                      apr_file_t *errfile,
1098                      const apr_array_header_t *changelists,
1099                      svn_client_ctx_t *ctx,
1100                      apr_pool_t *pool)
1101 {
1102   return svn_client_diff_peg5(options,
1103                               path,
1104                               peg_revision,
1105                               start_revision,
1106                               end_revision,
1107                               relative_to_dir,
1108                               depth,
1109                               ignore_ancestry,
1110                               no_diff_deleted,
1111                               FALSE,
1112                               ignore_content_type,
1113                               FALSE,
1114                               header_encoding,
1115                               outfile,
1116                               errfile,
1117                               changelists,
1118                               ctx,
1119                               pool);
1120 }
1121
1122 svn_error_t *
1123 svn_client_diff_peg3(const apr_array_header_t *options,
1124                      const char *path,
1125                      const svn_opt_revision_t *peg_revision,
1126                      const svn_opt_revision_t *start_revision,
1127                      const svn_opt_revision_t *end_revision,
1128                      svn_boolean_t recurse,
1129                      svn_boolean_t ignore_ancestry,
1130                      svn_boolean_t no_diff_deleted,
1131                      svn_boolean_t ignore_content_type,
1132                      const char *header_encoding,
1133                      apr_file_t *outfile,
1134                      apr_file_t *errfile,
1135                      svn_client_ctx_t *ctx,
1136                      apr_pool_t *pool)
1137 {
1138   return svn_client_diff_peg4(options,
1139                               path,
1140                               peg_revision,
1141                               start_revision,
1142                               end_revision,
1143                               NULL,
1144                               SVN_DEPTH_INFINITY_OR_FILES(recurse),
1145                               ignore_ancestry,
1146                               no_diff_deleted,
1147                               ignore_content_type,
1148                               header_encoding,
1149                               outfile,
1150                               errfile,
1151                               NULL,
1152                               ctx,
1153                               pool);
1154 }
1155
1156 svn_error_t *
1157 svn_client_diff_peg2(const apr_array_header_t *options,
1158                      const char *path,
1159                      const svn_opt_revision_t *peg_revision,
1160                      const svn_opt_revision_t *start_revision,
1161                      const svn_opt_revision_t *end_revision,
1162                      svn_boolean_t recurse,
1163                      svn_boolean_t ignore_ancestry,
1164                      svn_boolean_t no_diff_deleted,
1165                      svn_boolean_t ignore_content_type,
1166                      apr_file_t *outfile,
1167                      apr_file_t *errfile,
1168                      svn_client_ctx_t *ctx,
1169                      apr_pool_t *pool)
1170 {
1171   return svn_client_diff_peg3(options, path, peg_revision, start_revision,
1172                               end_revision,
1173                               SVN_DEPTH_INFINITY_OR_FILES(recurse),
1174                               ignore_ancestry, no_diff_deleted,
1175                               ignore_content_type, SVN_APR_LOCALE_CHARSET,
1176                               outfile, errfile, ctx, pool);
1177 }
1178
1179 svn_error_t *
1180 svn_client_diff_peg(const apr_array_header_t *options,
1181                     const char *path,
1182                     const svn_opt_revision_t *peg_revision,
1183                     const svn_opt_revision_t *start_revision,
1184                     const svn_opt_revision_t *end_revision,
1185                     svn_boolean_t recurse,
1186                     svn_boolean_t ignore_ancestry,
1187                     svn_boolean_t no_diff_deleted,
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_peg2(options, path, peg_revision,
1194                               start_revision, end_revision, recurse,
1195                               ignore_ancestry, no_diff_deleted, FALSE,
1196                               outfile, errfile, ctx, pool);
1197 }
1198
1199 svn_error_t *
1200 svn_client_diff_summarize(const char *path1,
1201                           const svn_opt_revision_t *revision1,
1202                           const char *path2,
1203                           const svn_opt_revision_t *revision2,
1204                           svn_boolean_t recurse,
1205                           svn_boolean_t ignore_ancestry,
1206                           svn_client_diff_summarize_func_t summarize_func,
1207                           void *summarize_baton,
1208                           svn_client_ctx_t *ctx,
1209                           apr_pool_t *pool)
1210 {
1211   return svn_client_diff_summarize2(path1, revision1, path2,
1212                                     revision2,
1213                                     SVN_DEPTH_INFINITY_OR_FILES(recurse),
1214                                     ignore_ancestry, NULL, summarize_func,
1215                                     summarize_baton, ctx, pool);
1216 }
1217
1218 svn_error_t *
1219 svn_client_diff_summarize_peg(const char *path,
1220                               const svn_opt_revision_t *peg_revision,
1221                               const svn_opt_revision_t *start_revision,
1222                               const svn_opt_revision_t *end_revision,
1223                               svn_boolean_t recurse,
1224                               svn_boolean_t ignore_ancestry,
1225                               svn_client_diff_summarize_func_t summarize_func,
1226                               void *summarize_baton,
1227                               svn_client_ctx_t *ctx,
1228                               apr_pool_t *pool)
1229 {
1230   return svn_client_diff_summarize_peg2(path, peg_revision,
1231                                         start_revision, end_revision,
1232                                         SVN_DEPTH_INFINITY_OR_FILES(recurse),
1233                                         ignore_ancestry, NULL,
1234                                         summarize_func, summarize_baton,
1235                                         ctx, pool);
1236 }
1237
1238 /*** From export.c ***/
1239 svn_error_t *
1240 svn_client_export4(svn_revnum_t *result_rev,
1241                    const char *from_path_or_url,
1242                    const char *to_path,
1243                    const svn_opt_revision_t *peg_revision,
1244                    const svn_opt_revision_t *revision,
1245                    svn_boolean_t overwrite,
1246                    svn_boolean_t ignore_externals,
1247                    svn_depth_t depth,
1248                    const char *native_eol,
1249                    svn_client_ctx_t *ctx,
1250                    apr_pool_t *pool)
1251 {
1252   return svn_client_export5(result_rev, from_path_or_url, to_path,
1253                             peg_revision, revision, overwrite, ignore_externals,
1254                             FALSE, depth, native_eol, ctx, pool);
1255 }
1256
1257 svn_error_t *
1258 svn_client_export3(svn_revnum_t *result_rev,
1259                    const char *from_path_or_url,
1260                    const char *to_path,
1261                    const svn_opt_revision_t *peg_revision,
1262                    const svn_opt_revision_t *revision,
1263                    svn_boolean_t overwrite,
1264                    svn_boolean_t ignore_externals,
1265                    svn_boolean_t recurse,
1266                    const char *native_eol,
1267                    svn_client_ctx_t *ctx,
1268                    apr_pool_t *pool)
1269 {
1270   return svn_client_export4(result_rev, from_path_or_url, to_path,
1271                             peg_revision, revision, overwrite, ignore_externals,
1272                             SVN_DEPTH_INFINITY_OR_FILES(recurse),
1273                             native_eol, ctx, pool);
1274 }
1275
1276 svn_error_t *
1277 svn_client_export2(svn_revnum_t *result_rev,
1278                    const char *from_path_or_url,
1279                    const char *to_path,
1280                    svn_opt_revision_t *revision,
1281                    svn_boolean_t force,
1282                    const char *native_eol,
1283                    svn_client_ctx_t *ctx,
1284                    apr_pool_t *pool)
1285 {
1286   svn_opt_revision_t peg_revision;
1287
1288   peg_revision.kind = svn_opt_revision_unspecified;
1289
1290   return svn_client_export3(result_rev, from_path_or_url, to_path,
1291                             &peg_revision, revision, force, FALSE, TRUE,
1292                             native_eol, ctx, pool);
1293 }
1294
1295
1296 svn_error_t *
1297 svn_client_export(svn_revnum_t *result_rev,
1298                   const char *from_path_or_url,
1299                   const char *to_path,
1300                   svn_opt_revision_t *revision,
1301                   svn_boolean_t force,
1302                   svn_client_ctx_t *ctx,
1303                   apr_pool_t *pool)
1304 {
1305   return svn_client_export2(result_rev, from_path_or_url, to_path, revision,
1306                             force, NULL, ctx, pool);
1307 }
1308
1309 /*** From list.c ***/
1310
1311 /* Baton for use with wrap_list_func */
1312 struct list_func_wrapper_baton {
1313     void *list_func1_baton;
1314     svn_client_list_func_t list_func1;
1315 };
1316
1317 /* This implements svn_client_list_func2_t */
1318 static svn_error_t *
1319 list_func_wrapper(void *baton,
1320                   const char *path,
1321                   const svn_dirent_t *dirent,
1322                   const svn_lock_t *lock,
1323                   const char *abs_path,
1324                   const char *external_parent_url,
1325                   const char *external_target,
1326                   apr_pool_t *scratch_pool)
1327 {
1328   struct list_func_wrapper_baton *lfwb = baton;
1329
1330   if (lfwb->list_func1)
1331     return lfwb->list_func1(lfwb->list_func1_baton, path, dirent,
1332                            lock, abs_path, scratch_pool);
1333
1334   return SVN_NO_ERROR;
1335 }
1336
1337 /* Helper function for svn_client_list2().  It wraps old format baton
1338    and callback function in list_func_wrapper_baton and
1339    returns new baton and callback to use with svn_client_list3(). */
1340 static void
1341 wrap_list_func(svn_client_list_func2_t *list_func2,
1342                void **list_func2_baton,
1343                svn_client_list_func_t list_func,
1344                void *baton,
1345                apr_pool_t *result_pool)
1346 {
1347   struct list_func_wrapper_baton *lfwb = apr_palloc(result_pool,
1348                                                     sizeof(*lfwb));
1349
1350   /* Set the user provided old format callback in the baton. */
1351   lfwb->list_func1_baton = baton;
1352   lfwb->list_func1 = list_func;
1353
1354   *list_func2_baton = lfwb;
1355   *list_func2 = list_func_wrapper;
1356 }
1357
1358 svn_error_t *
1359 svn_client_list2(const char *path_or_url,
1360                  const svn_opt_revision_t *peg_revision,
1361                  const svn_opt_revision_t *revision,
1362                  svn_depth_t depth,
1363                  apr_uint32_t dirent_fields,
1364                  svn_boolean_t fetch_locks,
1365                  svn_client_list_func_t list_func,
1366                  void *baton,
1367                  svn_client_ctx_t *ctx,
1368                  apr_pool_t *pool)
1369 {
1370   svn_client_list_func2_t list_func2;
1371   void *list_func2_baton;
1372
1373   wrap_list_func(&list_func2, &list_func2_baton, list_func, baton, pool);
1374
1375   return svn_client_list3(path_or_url, peg_revision, revision, depth,
1376                           dirent_fields, fetch_locks,
1377                           FALSE /* include externals */,
1378                           list_func2, list_func2_baton, ctx, pool);
1379 }
1380
1381 svn_error_t *
1382 svn_client_list(const char *path_or_url,
1383                 const svn_opt_revision_t *peg_revision,
1384                 const svn_opt_revision_t *revision,
1385                 svn_boolean_t recurse,
1386                 apr_uint32_t dirent_fields,
1387                 svn_boolean_t fetch_locks,
1388                 svn_client_list_func_t list_func,
1389                 void *baton,
1390                 svn_client_ctx_t *ctx,
1391                 apr_pool_t *pool)
1392 {
1393   return svn_client_list2(path_or_url,
1394                           peg_revision,
1395                           revision,
1396                           SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse),
1397                           dirent_fields,
1398                           fetch_locks,
1399                           list_func,
1400                           baton,
1401                           ctx,
1402                           pool);
1403 }
1404
1405 /* Baton used by compatibility wrapper svn_client_ls3. */
1406 struct ls_baton {
1407   apr_hash_t *dirents;
1408   apr_hash_t *locks;
1409   apr_pool_t *pool;
1410 };
1411
1412 /* This implements svn_client_list_func_t. */
1413 static svn_error_t *
1414 store_dirent(void *baton, const char *path, const svn_dirent_t *dirent,
1415              const svn_lock_t *lock, const char *abs_path, apr_pool_t *pool)
1416 {
1417   struct ls_baton *lb = baton;
1418
1419   /* The dirent is allocated in a temporary pool, so duplicate it into the
1420      correct pool.  Note, however, that the locks are stored in the correct
1421      pool already. */
1422   dirent = svn_dirent_dup(dirent, lb->pool);
1423
1424   /* An empty path means we are called for the target of the operation.
1425      For compatibility, we only store the target if it is a file, and we
1426      store it under the basename of the URL.  Note that this makes it
1427      impossible to differentiate between the target being a directory with a
1428      child with the same basename as the target and the target being a file,
1429      but that's how it was implemented. */
1430   if (path[0] == '\0')
1431     {
1432       if (dirent->kind == svn_node_file)
1433         {
1434           const char *base_name = svn_path_basename(abs_path, lb->pool);
1435           svn_hash_sets(lb->dirents, base_name, dirent);
1436           if (lock)
1437             svn_hash_sets(lb->locks, base_name, lock);
1438         }
1439     }
1440   else
1441     {
1442       path = apr_pstrdup(lb->pool, path);
1443       svn_hash_sets(lb->dirents, path, dirent);
1444       if (lock)
1445         svn_hash_sets(lb->locks, path, lock);
1446     }
1447
1448   return SVN_NO_ERROR;
1449 }
1450
1451 svn_error_t *
1452 svn_client_ls3(apr_hash_t **dirents,
1453                apr_hash_t **locks,
1454                const char *path_or_url,
1455                const svn_opt_revision_t *peg_revision,
1456                const svn_opt_revision_t *revision,
1457                svn_boolean_t recurse,
1458                svn_client_ctx_t *ctx,
1459                apr_pool_t *pool)
1460 {
1461   struct ls_baton lb;
1462
1463   *dirents = lb.dirents = apr_hash_make(pool);
1464   if (locks)
1465     *locks = lb.locks = apr_hash_make(pool);
1466   lb.pool = pool;
1467
1468   return svn_client_list(path_or_url, peg_revision, revision, recurse,
1469                          SVN_DIRENT_ALL, locks != NULL,
1470                          store_dirent, &lb, ctx, pool);
1471 }
1472
1473 svn_error_t *
1474 svn_client_ls2(apr_hash_t **dirents,
1475                const char *path_or_url,
1476                const svn_opt_revision_t *peg_revision,
1477                const svn_opt_revision_t *revision,
1478                svn_boolean_t recurse,
1479                svn_client_ctx_t *ctx,
1480                apr_pool_t *pool)
1481 {
1482
1483   return svn_client_ls3(dirents, NULL, path_or_url, peg_revision,
1484                         revision, recurse, ctx, pool);
1485 }
1486
1487
1488 svn_error_t *
1489 svn_client_ls(apr_hash_t **dirents,
1490               const char *path_or_url,
1491               svn_opt_revision_t *revision,
1492               svn_boolean_t recurse,
1493               svn_client_ctx_t *ctx,
1494               apr_pool_t *pool)
1495 {
1496   return svn_client_ls2(dirents, path_or_url, revision,
1497                         revision, recurse, ctx, pool);
1498 }
1499
1500 /*** From log.c ***/
1501 svn_error_t *
1502 svn_client_log4(const apr_array_header_t *targets,
1503                 const svn_opt_revision_t *peg_revision,
1504                 const svn_opt_revision_t *start,
1505                 const svn_opt_revision_t *end,
1506                 int limit,
1507                 svn_boolean_t discover_changed_paths,
1508                 svn_boolean_t strict_node_history,
1509                 svn_boolean_t include_merged_revisions,
1510                 const apr_array_header_t *revprops,
1511                 svn_log_entry_receiver_t receiver,
1512                 void *receiver_baton,
1513                 svn_client_ctx_t *ctx,
1514                 apr_pool_t *pool)
1515 {
1516   apr_array_header_t *revision_ranges;
1517
1518   revision_ranges = apr_array_make(pool, 1,
1519                                    sizeof(svn_opt_revision_range_t *));
1520   APR_ARRAY_PUSH(revision_ranges, svn_opt_revision_range_t *)
1521     = svn_opt__revision_range_create(start, end, pool);
1522
1523   return svn_client_log5(targets, peg_revision, revision_ranges, limit,
1524                          discover_changed_paths, strict_node_history,
1525                          include_merged_revisions, revprops, receiver,
1526                          receiver_baton, ctx, pool);
1527 }
1528
1529
1530 svn_error_t *
1531 svn_client_log3(const apr_array_header_t *targets,
1532                 const svn_opt_revision_t *peg_revision,
1533                 const svn_opt_revision_t *start,
1534                 const svn_opt_revision_t *end,
1535                 int limit,
1536                 svn_boolean_t discover_changed_paths,
1537                 svn_boolean_t strict_node_history,
1538                 svn_log_message_receiver_t receiver,
1539                 void *receiver_baton,
1540                 svn_client_ctx_t *ctx,
1541                 apr_pool_t *pool)
1542 {
1543   svn_log_entry_receiver_t receiver2;
1544   void *receiver2_baton;
1545
1546   svn_compat_wrap_log_receiver(&receiver2, &receiver2_baton,
1547                                receiver, receiver_baton,
1548                                pool);
1549
1550   return svn_client_log4(targets, peg_revision, start, end, limit,
1551                          discover_changed_paths, strict_node_history, FALSE,
1552                          svn_compat_log_revprops_in(pool),
1553                          receiver2, receiver2_baton, ctx, pool);
1554 }
1555
1556 svn_error_t *
1557 svn_client_log2(const apr_array_header_t *targets,
1558                 const svn_opt_revision_t *start,
1559                 const svn_opt_revision_t *end,
1560                 int limit,
1561                 svn_boolean_t discover_changed_paths,
1562                 svn_boolean_t strict_node_history,
1563                 svn_log_message_receiver_t receiver,
1564                 void *receiver_baton,
1565                 svn_client_ctx_t *ctx,
1566                 apr_pool_t *pool)
1567 {
1568   svn_opt_revision_t peg_revision;
1569   peg_revision.kind = svn_opt_revision_unspecified;
1570   return svn_client_log3(targets, &peg_revision, start, end, limit,
1571                          discover_changed_paths, strict_node_history,
1572                          receiver, receiver_baton, ctx, pool);
1573 }
1574
1575 svn_error_t *
1576 svn_client_log(const apr_array_header_t *targets,
1577                const svn_opt_revision_t *start,
1578                const svn_opt_revision_t *end,
1579                svn_boolean_t discover_changed_paths,
1580                svn_boolean_t strict_node_history,
1581                svn_log_message_receiver_t receiver,
1582                void *receiver_baton,
1583                svn_client_ctx_t *ctx,
1584                apr_pool_t *pool)
1585 {
1586   svn_error_t *err = SVN_NO_ERROR;
1587
1588   err = svn_client_log2(targets, start, end, 0, discover_changed_paths,
1589                         strict_node_history, receiver, receiver_baton, ctx,
1590                         pool);
1591
1592   /* Special case: If there have been no commits, we'll get an error
1593    * for requesting log of a revision higher than 0.  But the
1594    * default behavior of "svn log" is to give revisions HEAD through
1595    * 1, on the assumption that HEAD >= 1.
1596    *
1597    * So if we got that error for that reason, and it looks like the
1598    * user was just depending on the defaults (rather than explicitly
1599    * requesting the log for revision 1), then we don't error.  Instead
1600    * we just invoke the receiver manually on a hand-constructed log
1601    * message for revision 0.
1602    *
1603    * See also http://subversion.tigris.org/issues/show_bug.cgi?id=692.
1604    */
1605   if (err && (err->apr_err == SVN_ERR_FS_NO_SUCH_REVISION)
1606       && (start->kind == svn_opt_revision_head)
1607       && ((end->kind == svn_opt_revision_number)
1608           && (end->value.number == 1)))
1609     {
1610
1611       /* We don't need to check if HEAD is 0, because that must be the case,
1612        * by logical deduction: The revision range specified is HEAD:1.
1613        * HEAD cannot not exist, so the revision to which "no such revision"
1614        * applies is 1. If revision 1 does not exist, then HEAD is 0.
1615        * Hence, we deduce the repository is empty without needing access
1616        * to further information. */
1617
1618       svn_error_clear(err);
1619       err = SVN_NO_ERROR;
1620
1621       /* Log receivers are free to handle revision 0 specially... But
1622          just in case some don't, we make up a message here. */
1623       SVN_ERR(receiver(receiver_baton,
1624                        NULL, 0, "", "", _("No commits in repository"),
1625                        pool));
1626     }
1627
1628   return svn_error_trace(err);
1629 }
1630
1631 /*** From merge.c ***/
1632
1633 svn_error_t *
1634 svn_client_merge4(const char *source1,
1635                   const svn_opt_revision_t *revision1,
1636                   const char *source2,
1637                   const svn_opt_revision_t *revision2,
1638                   const char *target_wcpath,
1639                   svn_depth_t depth,
1640                   svn_boolean_t ignore_ancestry,
1641                   svn_boolean_t force_delete,
1642                   svn_boolean_t record_only,
1643                   svn_boolean_t dry_run,
1644                   svn_boolean_t allow_mixed_rev,
1645                   const apr_array_header_t *merge_options,
1646                   svn_client_ctx_t *ctx,
1647                   apr_pool_t *pool)
1648 {
1649   SVN_ERR(svn_client_merge5(source1, revision1,
1650                             source2, revision2,
1651                             target_wcpath,
1652                             depth,
1653                             ignore_ancestry /*ignore_mergeinfo*/,
1654                             ignore_ancestry /*diff_ignore_ancestry*/,
1655                             force_delete, record_only,
1656                             dry_run, allow_mixed_rev,
1657                             merge_options, ctx, pool));
1658   return SVN_NO_ERROR;
1659 }
1660
1661 svn_error_t *
1662 svn_client_merge3(const char *source1,
1663                   const svn_opt_revision_t *revision1,
1664                   const char *source2,
1665                   const svn_opt_revision_t *revision2,
1666                   const char *target_wcpath,
1667                   svn_depth_t depth,
1668                   svn_boolean_t ignore_ancestry,
1669                   svn_boolean_t force,
1670                   svn_boolean_t record_only,
1671                   svn_boolean_t dry_run,
1672                   const apr_array_header_t *merge_options,
1673                   svn_client_ctx_t *ctx,
1674                   apr_pool_t *pool)
1675 {
1676   return svn_client_merge4(source1, revision1, source2, revision2,
1677                            target_wcpath, depth, ignore_ancestry, force,
1678                            record_only, dry_run, TRUE, merge_options,
1679                            ctx, pool);
1680 }
1681
1682 svn_error_t *
1683 svn_client_merge2(const char *source1,
1684                   const svn_opt_revision_t *revision1,
1685                   const char *source2,
1686                   const svn_opt_revision_t *revision2,
1687                   const char *target_wcpath,
1688                   svn_boolean_t recurse,
1689                   svn_boolean_t ignore_ancestry,
1690                   svn_boolean_t force,
1691                   svn_boolean_t dry_run,
1692                   const apr_array_header_t *merge_options,
1693                   svn_client_ctx_t *ctx,
1694                   apr_pool_t *pool)
1695 {
1696   return svn_client_merge3(source1, revision1, source2, revision2,
1697                            target_wcpath,
1698                            SVN_DEPTH_INFINITY_OR_FILES(recurse),
1699                            ignore_ancestry, force, FALSE, dry_run,
1700                            merge_options, ctx, pool);
1701 }
1702
1703 svn_error_t *
1704 svn_client_merge(const char *source1,
1705                  const svn_opt_revision_t *revision1,
1706                  const char *source2,
1707                  const svn_opt_revision_t *revision2,
1708                  const char *target_wcpath,
1709                  svn_boolean_t recurse,
1710                  svn_boolean_t ignore_ancestry,
1711                  svn_boolean_t force,
1712                  svn_boolean_t dry_run,
1713                  svn_client_ctx_t *ctx,
1714                  apr_pool_t *pool)
1715 {
1716   return svn_client_merge2(source1, revision1, source2, revision2,
1717                            target_wcpath, recurse, ignore_ancestry, force,
1718                            dry_run, NULL, ctx, pool);
1719 }
1720
1721 svn_error_t *
1722 svn_client_merge_peg4(const char *source_path_or_url,
1723                       const apr_array_header_t *ranges_to_merge,
1724                       const svn_opt_revision_t *source_peg_revision,
1725                       const char *target_wcpath,
1726                       svn_depth_t depth,
1727                       svn_boolean_t ignore_ancestry,
1728                       svn_boolean_t force_delete,
1729                       svn_boolean_t record_only,
1730                       svn_boolean_t dry_run,
1731                       svn_boolean_t allow_mixed_rev,
1732                       const apr_array_header_t *merge_options,
1733                       svn_client_ctx_t *ctx,
1734                       apr_pool_t *pool)
1735 {
1736   SVN_ERR(svn_client_merge_peg5(source_path_or_url,
1737                                 ranges_to_merge,
1738                                 source_peg_revision,
1739                                 target_wcpath,
1740                                 depth,
1741                                 ignore_ancestry /*ignore_mergeinfo*/,
1742                                 ignore_ancestry /*diff_ignore_ancestry*/,
1743                                 force_delete, record_only,
1744                                 dry_run, allow_mixed_rev,
1745                                 merge_options, ctx, pool));
1746   return SVN_NO_ERROR;
1747 }
1748
1749 svn_error_t *
1750 svn_client_merge_peg3(const char *source,
1751                       const apr_array_header_t *ranges_to_merge,
1752                       const svn_opt_revision_t *peg_revision,
1753                       const char *target_wcpath,
1754                       svn_depth_t depth,
1755                       svn_boolean_t ignore_ancestry,
1756                       svn_boolean_t force,
1757                       svn_boolean_t record_only,
1758                       svn_boolean_t dry_run,
1759                       const apr_array_header_t *merge_options,
1760                       svn_client_ctx_t *ctx,
1761                       apr_pool_t *pool)
1762 {
1763   return svn_client_merge_peg4(source, ranges_to_merge, peg_revision,
1764                                target_wcpath, depth, ignore_ancestry, force,
1765                                record_only, dry_run, TRUE, merge_options,
1766                                ctx, pool);
1767 }
1768
1769 svn_error_t *
1770 svn_client_merge_peg2(const char *source,
1771                       const svn_opt_revision_t *revision1,
1772                       const svn_opt_revision_t *revision2,
1773                       const svn_opt_revision_t *peg_revision,
1774                       const char *target_wcpath,
1775                       svn_boolean_t recurse,
1776                       svn_boolean_t ignore_ancestry,
1777                       svn_boolean_t force,
1778                       svn_boolean_t dry_run,
1779                       const apr_array_header_t *merge_options,
1780                       svn_client_ctx_t *ctx,
1781                       apr_pool_t *pool)
1782 {
1783   apr_array_header_t *ranges_to_merge =
1784     apr_array_make(pool, 1, sizeof(svn_opt_revision_range_t *));
1785
1786   APR_ARRAY_PUSH(ranges_to_merge, svn_opt_revision_range_t *)
1787     = svn_opt__revision_range_create(revision1, revision2, pool);
1788   return svn_client_merge_peg3(source, ranges_to_merge,
1789                                peg_revision,
1790                                target_wcpath,
1791                                SVN_DEPTH_INFINITY_OR_FILES(recurse),
1792                                ignore_ancestry, force, FALSE, dry_run,
1793                                merge_options, ctx, pool);
1794 }
1795
1796 svn_error_t *
1797 svn_client_merge_peg(const char *source,
1798                      const svn_opt_revision_t *revision1,
1799                      const svn_opt_revision_t *revision2,
1800                      const svn_opt_revision_t *peg_revision,
1801                      const char *target_wcpath,
1802                      svn_boolean_t recurse,
1803                      svn_boolean_t ignore_ancestry,
1804                      svn_boolean_t force,
1805                      svn_boolean_t dry_run,
1806                      svn_client_ctx_t *ctx,
1807                      apr_pool_t *pool)
1808 {
1809   return svn_client_merge_peg2(source, revision1, revision2, peg_revision,
1810                                target_wcpath, recurse, ignore_ancestry, force,
1811                                dry_run, NULL, ctx, pool);
1812 }
1813
1814 /*** From prop_commands.c ***/
1815 svn_error_t *
1816 svn_client_propset3(svn_commit_info_t **commit_info_p,
1817                     const char *propname,
1818                     const svn_string_t *propval,
1819                     const char *target,
1820                     svn_depth_t depth,
1821                     svn_boolean_t skip_checks,
1822                     svn_revnum_t base_revision_for_url,
1823                     const apr_array_header_t *changelists,
1824                     const apr_hash_t *revprop_table,
1825                     svn_client_ctx_t *ctx,
1826                     apr_pool_t *pool)
1827 {
1828   if (svn_path_is_url(target))
1829     {
1830       struct capture_baton_t cb;
1831
1832       cb.info = commit_info_p;
1833       cb.pool = pool;
1834
1835       SVN_ERR(svn_client_propset_remote(propname, propval, target, skip_checks,
1836                                         base_revision_for_url, revprop_table,
1837                                         capture_commit_info, &cb, ctx, pool));
1838     }
1839   else
1840     {
1841       apr_array_header_t *targets = apr_array_make(pool, 1,
1842                                                    sizeof(const char *));
1843
1844       APR_ARRAY_PUSH(targets, const char *) = target;
1845       SVN_ERR(svn_client_propset_local(propname, propval, targets, depth,
1846                                        skip_checks, changelists, ctx, pool));
1847     }
1848
1849   return SVN_NO_ERROR;
1850 }
1851
1852 svn_error_t *
1853 svn_client_propset2(const char *propname,
1854                     const svn_string_t *propval,
1855                     const char *target,
1856                     svn_boolean_t recurse,
1857                     svn_boolean_t skip_checks,
1858                     svn_client_ctx_t *ctx,
1859                     apr_pool_t *pool)
1860 {
1861   return svn_client_propset3(NULL, propname, propval, target,
1862                              SVN_DEPTH_INFINITY_OR_EMPTY(recurse),
1863                              skip_checks, SVN_INVALID_REVNUM,
1864                              NULL, NULL, ctx, pool);
1865 }
1866
1867
1868 svn_error_t *
1869 svn_client_propset(const char *propname,
1870                    const svn_string_t *propval,
1871                    const char *target,
1872                    svn_boolean_t recurse,
1873                    apr_pool_t *pool)
1874 {
1875   svn_client_ctx_t *ctx;
1876
1877   SVN_ERR(svn_client_create_context(&ctx, pool));
1878
1879   return svn_client_propset2(propname, propval, target, recurse, FALSE,
1880                              ctx, pool);
1881 }
1882
1883 svn_error_t *
1884 svn_client_revprop_set(const char *propname,
1885                        const svn_string_t *propval,
1886                        const char *URL,
1887                        const svn_opt_revision_t *revision,
1888                        svn_revnum_t *set_rev,
1889                        svn_boolean_t force,
1890                        svn_client_ctx_t *ctx,
1891                        apr_pool_t *pool)
1892 {
1893   return svn_client_revprop_set2(propname, propval, NULL, URL,
1894                                  revision, set_rev, force, ctx, pool);
1895
1896 }
1897
1898 svn_error_t *
1899 svn_client_propget4(apr_hash_t **props,
1900                     const char *propname,
1901                     const char *target,
1902                     const svn_opt_revision_t *peg_revision,
1903                     const svn_opt_revision_t *revision,
1904                     svn_revnum_t *actual_revnum,
1905                     svn_depth_t depth,
1906                     const apr_array_header_t *changelists,
1907                     svn_client_ctx_t *ctx,
1908                     apr_pool_t *result_pool,
1909                     apr_pool_t *scratch_pool)
1910 {
1911   return svn_error_trace(svn_client_propget5(props, NULL, propname, target,
1912                                              peg_revision, revision,
1913                                              actual_revnum, depth,
1914                                              changelists, ctx,
1915                                              result_pool, scratch_pool));
1916 }
1917
1918 svn_error_t *
1919 svn_client_propget3(apr_hash_t **props,
1920                     const char *propname,
1921                     const char *path_or_url,
1922                     const svn_opt_revision_t *peg_revision,
1923                     const svn_opt_revision_t *revision,
1924                     svn_revnum_t *actual_revnum,
1925                     svn_depth_t depth,
1926                     const apr_array_header_t *changelists,
1927                     svn_client_ctx_t *ctx,
1928                     apr_pool_t *pool)
1929 {
1930   const char *target;
1931   apr_hash_t *temp_props;
1932   svn_error_t *err;
1933
1934   if (svn_path_is_url(path_or_url))
1935     target = path_or_url;
1936   else
1937     SVN_ERR(svn_dirent_get_absolute(&target, path_or_url, pool));
1938
1939   err = svn_client_propget4(&temp_props, propname, target,
1940                             peg_revision, revision, actual_revnum,
1941                             depth, changelists, ctx, pool, pool);
1942
1943   if (err && err->apr_err == SVN_ERR_UNVERSIONED_RESOURCE)
1944     {
1945       err->apr_err = SVN_ERR_ENTRY_NOT_FOUND;
1946       return svn_error_trace(err);
1947     }
1948   else
1949     SVN_ERR(err);
1950
1951   if (actual_revnum
1952         && !svn_path_is_url(path_or_url)
1953         && !SVN_IS_VALID_REVNUM(*actual_revnum))
1954     {
1955       /* Get the actual_revnum; added nodes have no revision yet, and old
1956        * callers expected the mock-up revision of 0. */
1957       svn_boolean_t added;
1958
1959       SVN_ERR(svn_wc__node_is_added(&added, ctx->wc_ctx, target, pool));
1960       if (added)
1961         *actual_revnum = 0;
1962     }
1963
1964   /* We may need to fix up our hash keys for legacy callers. */
1965   if (!svn_path_is_url(path_or_url) && strcmp(target, path_or_url) != 0)
1966     {
1967       apr_hash_index_t *hi;
1968
1969       *props = apr_hash_make(pool);
1970       for (hi = apr_hash_first(pool, temp_props); hi;
1971             hi = apr_hash_next(hi))
1972         {
1973           const char *abspath = svn__apr_hash_index_key(hi);
1974           svn_string_t *value = svn__apr_hash_index_val(hi);
1975           const char *relpath = svn_dirent_join(path_or_url,
1976                                      svn_dirent_skip_ancestor(target, abspath),
1977                                      pool);
1978
1979           svn_hash_sets(*props, relpath, value);
1980         }
1981     }
1982   else
1983     *props = temp_props;
1984
1985   return SVN_NO_ERROR;
1986 }
1987
1988 svn_error_t *
1989 svn_client_propget2(apr_hash_t **props,
1990                     const char *propname,
1991                     const char *target,
1992                     const svn_opt_revision_t *peg_revision,
1993                     const svn_opt_revision_t *revision,
1994                     svn_boolean_t recurse,
1995                     svn_client_ctx_t *ctx,
1996                     apr_pool_t *pool)
1997 {
1998   return svn_client_propget3(props,
1999                              propname,
2000                              target,
2001                              peg_revision,
2002                              revision,
2003                              NULL,
2004                              SVN_DEPTH_INFINITY_OR_EMPTY(recurse),
2005                              NULL,
2006                              ctx,
2007                              pool);
2008 }
2009
2010 svn_error_t *
2011 svn_client_propget(apr_hash_t **props,
2012                    const char *propname,
2013                    const char *target,
2014                    const svn_opt_revision_t *revision,
2015                    svn_boolean_t recurse,
2016                    svn_client_ctx_t *ctx,
2017                    apr_pool_t *pool)
2018 {
2019   return svn_client_propget2(props, propname, target, revision, revision,
2020                              recurse, ctx, pool);
2021 }
2022
2023
2024 /* Duplicate a HASH containing (char * -> svn_string_t *) key/value
2025    pairs using POOL. */
2026 static apr_hash_t *
2027 string_hash_dup(apr_hash_t *hash, apr_pool_t *pool)
2028 {
2029   apr_hash_index_t *hi;
2030   apr_hash_t *new_hash = apr_hash_make(pool);
2031
2032   for (hi = apr_hash_first(pool, hash); hi; hi = apr_hash_next(hi))
2033     {
2034       const char *key = apr_pstrdup(pool, svn__apr_hash_index_key(hi));
2035       apr_ssize_t klen = svn__apr_hash_index_klen(hi);
2036       svn_string_t *val = svn_string_dup(svn__apr_hash_index_val(hi), pool);
2037
2038       apr_hash_set(new_hash, key, klen, val);
2039     }
2040   return new_hash;
2041 }
2042
2043 svn_client_proplist_item_t *
2044 svn_client_proplist_item_dup(const svn_client_proplist_item_t *item,
2045                              apr_pool_t * pool)
2046 {
2047   svn_client_proplist_item_t *new_item = apr_pcalloc(pool, sizeof(*new_item));
2048
2049   if (item->node_name)
2050     new_item->node_name = svn_stringbuf_dup(item->node_name, pool);
2051
2052   if (item->prop_hash)
2053     new_item->prop_hash = string_hash_dup(item->prop_hash, pool);
2054
2055   return new_item;
2056 }
2057
2058 /* Baton for use with wrap_proplist_receiver */
2059 struct proplist_receiver_wrapper_baton {
2060   void *baton;
2061   svn_proplist_receiver_t receiver;
2062 };
2063
2064 /* This implements svn_client_proplist_receiver2_t */
2065 static svn_error_t *
2066 proplist_wrapper_receiver(void *baton,
2067                           const char *path,
2068                           apr_hash_t *prop_hash,
2069                           apr_array_header_t *inherited_props,
2070                           apr_pool_t *pool)
2071 {
2072   struct proplist_receiver_wrapper_baton *plrwb = baton;
2073
2074   if (plrwb->receiver)
2075     return plrwb->receiver(plrwb->baton, path, prop_hash, pool);
2076
2077   return SVN_NO_ERROR;
2078 }
2079
2080 static void
2081 wrap_proplist_receiver(svn_proplist_receiver2_t *receiver2,
2082                        void **receiver2_baton,
2083                        svn_proplist_receiver_t receiver,
2084                        void *receiver_baton,
2085                        apr_pool_t *pool)
2086 {
2087   struct proplist_receiver_wrapper_baton *plrwb = apr_palloc(pool,
2088                                                              sizeof(*plrwb));
2089
2090   /* Set the user provided old format callback in the baton. */
2091   plrwb->baton = receiver_baton;
2092   plrwb->receiver = receiver;
2093
2094   *receiver2_baton = plrwb;
2095   *receiver2 = proplist_wrapper_receiver;
2096 }
2097
2098 svn_error_t *
2099 svn_client_proplist3(const char *target,
2100                      const svn_opt_revision_t *peg_revision,
2101                      const svn_opt_revision_t *revision,
2102                      svn_depth_t depth,
2103                      const apr_array_header_t *changelists,
2104                      svn_proplist_receiver_t receiver,
2105                      void *receiver_baton,
2106                      svn_client_ctx_t *ctx,
2107                      apr_pool_t *pool)
2108 {
2109
2110   svn_proplist_receiver2_t receiver2;
2111   void *receiver2_baton;
2112
2113   wrap_proplist_receiver(&receiver2, &receiver2_baton, receiver, receiver_baton,
2114                          pool);
2115
2116   return svn_error_trace(svn_client_proplist4(target, peg_revision, revision,
2117                                               depth, changelists, FALSE,
2118                                               receiver2, receiver2_baton,
2119                                               ctx, pool));
2120 }
2121
2122 /* Receiver baton used by proplist2() */
2123 struct proplist_receiver_baton {
2124   apr_array_header_t *props;
2125   apr_pool_t *pool;
2126 };
2127
2128 /* Receiver function used by proplist2(). */
2129 static svn_error_t *
2130 proplist_receiver_cb(void *baton,
2131                      const char *path,
2132                      apr_hash_t *prop_hash,
2133                      apr_pool_t *pool)
2134 {
2135   struct proplist_receiver_baton *pl_baton =
2136     (struct proplist_receiver_baton *) baton;
2137   svn_client_proplist_item_t *tmp_item = apr_palloc(pool, sizeof(*tmp_item));
2138   svn_client_proplist_item_t *item;
2139
2140   /* Because the pool passed to the receiver function is likely to be a
2141      temporary pool of some kind, we need to make copies of *path and
2142      *prop_hash in the pool provided by the baton. */
2143   tmp_item->node_name = svn_stringbuf_create(path, pl_baton->pool);
2144   tmp_item->prop_hash = prop_hash;
2145
2146   item = svn_client_proplist_item_dup(tmp_item, pl_baton->pool);
2147
2148   APR_ARRAY_PUSH(pl_baton->props, const svn_client_proplist_item_t *) = item;
2149
2150   return SVN_NO_ERROR;
2151 }
2152
2153 svn_error_t *
2154 svn_client_proplist2(apr_array_header_t **props,
2155                      const char *target,
2156                      const svn_opt_revision_t *peg_revision,
2157                      const svn_opt_revision_t *revision,
2158                      svn_boolean_t recurse,
2159                      svn_client_ctx_t *ctx,
2160                      apr_pool_t *pool)
2161 {
2162   struct proplist_receiver_baton pl_baton;
2163
2164   *props = apr_array_make(pool, 5, sizeof(svn_client_proplist_item_t *));
2165   pl_baton.props = *props;
2166   pl_baton.pool = pool;
2167
2168   return svn_client_proplist3(target, peg_revision, revision,
2169                               SVN_DEPTH_INFINITY_OR_EMPTY(recurse), NULL,
2170                               proplist_receiver_cb, &pl_baton, ctx, pool);
2171 }
2172
2173
2174 svn_error_t *
2175 svn_client_proplist(apr_array_header_t **props,
2176                     const char *target,
2177                     const svn_opt_revision_t *revision,
2178                     svn_boolean_t recurse,
2179                     svn_client_ctx_t *ctx,
2180                     apr_pool_t *pool)
2181 {
2182   return svn_client_proplist2(props, target, revision, revision,
2183                               recurse, ctx, pool);
2184 }
2185
2186 /*** From status.c ***/
2187
2188 struct status4_wrapper_baton
2189 {
2190   svn_wc_context_t *wc_ctx;
2191   svn_wc_status_func3_t old_func;
2192   void *old_baton;
2193 };
2194
2195 /* Implements svn_client_status_func_t */
2196 static svn_error_t *
2197 status4_wrapper_func(void *baton,
2198                      const char *path,
2199                      const svn_client_status_t *status,
2200                      apr_pool_t *scratch_pool)
2201 {
2202   struct status4_wrapper_baton *swb = baton;
2203   svn_wc_status2_t *dup;
2204   const char *local_abspath;
2205   const svn_wc_status3_t *wc_status = status->backwards_compatibility_baton;
2206
2207   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
2208   SVN_ERR(svn_wc__status2_from_3(&dup, wc_status, swb->wc_ctx,
2209                                  local_abspath, scratch_pool,
2210                                  scratch_pool));
2211
2212   return (*swb->old_func)(swb->old_baton, path, dup, scratch_pool);
2213 }
2214
2215 svn_error_t *
2216 svn_client_status4(svn_revnum_t *result_rev,
2217                    const char *path,
2218                    const svn_opt_revision_t *revision,
2219                    svn_wc_status_func3_t status_func,
2220                    void *status_baton,
2221                    svn_depth_t depth,
2222                    svn_boolean_t get_all,
2223                    svn_boolean_t update,
2224                    svn_boolean_t no_ignore,
2225                    svn_boolean_t ignore_externals,
2226                    const apr_array_header_t *changelists,
2227                    svn_client_ctx_t *ctx,
2228                    apr_pool_t *pool)
2229 {
2230   struct status4_wrapper_baton swb;
2231
2232   swb.wc_ctx = ctx->wc_ctx;
2233   swb.old_func = status_func;
2234   swb.old_baton = status_baton;
2235
2236   return svn_client_status5(result_rev, ctx, path, revision, depth, get_all,
2237                             update, no_ignore, ignore_externals, TRUE,
2238                             changelists, status4_wrapper_func, &swb, pool);
2239 }
2240
2241 struct status3_wrapper_baton
2242 {
2243   svn_wc_status_func2_t old_func;
2244   void *old_baton;
2245 };
2246
2247 static svn_error_t *
2248 status3_wrapper_func(void *baton,
2249                      const char *path,
2250                      svn_wc_status2_t *status,
2251                      apr_pool_t *pool)
2252 {
2253   struct status3_wrapper_baton *swb = baton;
2254
2255   swb->old_func(swb->old_baton, path, status);
2256   return SVN_NO_ERROR;
2257 }
2258
2259 svn_error_t *
2260 svn_client_status3(svn_revnum_t *result_rev,
2261                    const char *path,
2262                    const svn_opt_revision_t *revision,
2263                    svn_wc_status_func2_t status_func,
2264                    void *status_baton,
2265                    svn_depth_t depth,
2266                    svn_boolean_t get_all,
2267                    svn_boolean_t update,
2268                    svn_boolean_t no_ignore,
2269                    svn_boolean_t ignore_externals,
2270                    const apr_array_header_t *changelists,
2271                    svn_client_ctx_t *ctx,
2272                    apr_pool_t *pool)
2273 {
2274   struct status3_wrapper_baton swb = { 0 };
2275   swb.old_func = status_func;
2276   swb.old_baton = status_baton;
2277   return svn_client_status4(result_rev, path, revision, status3_wrapper_func,
2278                             &swb, depth, get_all, update, no_ignore,
2279                             ignore_externals, changelists, ctx, pool);
2280 }
2281
2282 svn_error_t *
2283 svn_client_status2(svn_revnum_t *result_rev,
2284                    const char *path,
2285                    const svn_opt_revision_t *revision,
2286                    svn_wc_status_func2_t status_func,
2287                    void *status_baton,
2288                    svn_boolean_t recurse,
2289                    svn_boolean_t get_all,
2290                    svn_boolean_t update,
2291                    svn_boolean_t no_ignore,
2292                    svn_boolean_t ignore_externals,
2293                    svn_client_ctx_t *ctx,
2294                    apr_pool_t *pool)
2295 {
2296   return svn_client_status3(result_rev, path, revision,
2297                             status_func, status_baton,
2298                             SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse),
2299                             get_all, update, no_ignore, ignore_externals, NULL,
2300                             ctx, pool);
2301 }
2302
2303
2304 /* Baton for old_status_func_cb; does what you think it does. */
2305 struct old_status_func_cb_baton
2306 {
2307   svn_wc_status_func_t original_func;
2308   void *original_baton;
2309 };
2310
2311 /* Help svn_client_status() accept an old-style status func and baton,
2312    by wrapping them before passing along to svn_client_status2().
2313
2314    This implements the 'svn_wc_status_func2_t' function type. */
2315 static void old_status_func_cb(void *baton,
2316                                const char *path,
2317                                svn_wc_status2_t *status)
2318 {
2319   struct old_status_func_cb_baton *b = baton;
2320   svn_wc_status_t *stat = (svn_wc_status_t *) status;
2321
2322   b->original_func(b->original_baton, path, stat);
2323 }
2324
2325
2326 svn_error_t *
2327 svn_client_status(svn_revnum_t *result_rev,
2328                   const char *path,
2329                   svn_opt_revision_t *revision,
2330                   svn_wc_status_func_t status_func,
2331                   void *status_baton,
2332                   svn_boolean_t recurse,
2333                   svn_boolean_t get_all,
2334                   svn_boolean_t update,
2335                   svn_boolean_t no_ignore,
2336                   svn_client_ctx_t *ctx,
2337                   apr_pool_t *pool)
2338 {
2339   struct old_status_func_cb_baton *b = apr_pcalloc(pool, sizeof(*b));
2340   b->original_func = status_func;
2341   b->original_baton = status_baton;
2342
2343   return svn_client_status2(result_rev, path, revision,
2344                             old_status_func_cb, b,
2345                             recurse, get_all, update, no_ignore, FALSE,
2346                             ctx, pool);
2347 }
2348
2349 /*** From update.c ***/
2350 svn_error_t *
2351 svn_client_update3(apr_array_header_t **result_revs,
2352                    const apr_array_header_t *paths,
2353                    const svn_opt_revision_t *revision,
2354                    svn_depth_t depth,
2355                    svn_boolean_t depth_is_sticky,
2356                    svn_boolean_t ignore_externals,
2357                    svn_boolean_t allow_unver_obstructions,
2358                    svn_client_ctx_t *ctx,
2359                    apr_pool_t *pool)
2360 {
2361   return svn_client_update4(result_revs, paths, revision,
2362                             depth, depth_is_sticky, ignore_externals,
2363                             allow_unver_obstructions, TRUE, FALSE,
2364                             ctx, pool);
2365 }
2366
2367 svn_error_t *
2368 svn_client_update2(apr_array_header_t **result_revs,
2369                    const apr_array_header_t *paths,
2370                    const svn_opt_revision_t *revision,
2371                    svn_boolean_t recurse,
2372                    svn_boolean_t ignore_externals,
2373                    svn_client_ctx_t *ctx,
2374                    apr_pool_t *pool)
2375 {
2376   return svn_client_update3(result_revs, paths, revision,
2377                             SVN_DEPTH_INFINITY_OR_FILES(recurse), FALSE,
2378                             ignore_externals, FALSE, ctx, pool);
2379 }
2380
2381 svn_error_t *
2382 svn_client_update(svn_revnum_t *result_rev,
2383                   const char *path,
2384                   const svn_opt_revision_t *revision,
2385                   svn_boolean_t recurse,
2386                   svn_client_ctx_t *ctx,
2387                   apr_pool_t *pool)
2388 {
2389   apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(const char *));
2390   apr_array_header_t *result_revs;
2391
2392   APR_ARRAY_PUSH(paths, const char *) = path;
2393
2394   SVN_ERR(svn_client_update2(&result_revs, paths, revision, recurse, FALSE,
2395                              ctx, pool));
2396
2397   *result_rev = APR_ARRAY_IDX(result_revs, 0, svn_revnum_t);
2398
2399   return SVN_NO_ERROR;
2400 }
2401
2402 /*** From switch.c ***/
2403 svn_error_t *
2404 svn_client_switch2(svn_revnum_t *result_rev,
2405                    const char *path,
2406                    const char *switch_url,
2407                    const svn_opt_revision_t *peg_revision,
2408                    const svn_opt_revision_t *revision,
2409                    svn_depth_t depth,
2410                    svn_boolean_t depth_is_sticky,
2411                    svn_boolean_t ignore_externals,
2412                    svn_boolean_t allow_unver_obstructions,
2413                    svn_client_ctx_t *ctx,
2414                    apr_pool_t *pool)
2415 {
2416   return svn_client_switch3(result_rev, path, switch_url, peg_revision,
2417                             revision, depth, depth_is_sticky, ignore_externals,
2418                             allow_unver_obstructions,
2419                             TRUE /* ignore_ancestry */,
2420                             ctx, pool);
2421 }
2422
2423 svn_error_t *
2424 svn_client_switch(svn_revnum_t *result_rev,
2425                   const char *path,
2426                   const char *switch_url,
2427                   const svn_opt_revision_t *revision,
2428                   svn_boolean_t recurse,
2429                   svn_client_ctx_t *ctx,
2430                   apr_pool_t *pool)
2431 {
2432   svn_opt_revision_t peg_revision;
2433   peg_revision.kind = svn_opt_revision_unspecified;
2434   return svn_client_switch2(result_rev, path, switch_url,
2435                             &peg_revision, revision,
2436                             SVN_DEPTH_INFINITY_OR_FILES(recurse),
2437                             FALSE, FALSE, FALSE, ctx, pool);
2438 }
2439
2440 /*** From cat.c ***/
2441 svn_error_t *
2442 svn_client_cat(svn_stream_t *out,
2443                const char *path_or_url,
2444                const svn_opt_revision_t *revision,
2445                svn_client_ctx_t *ctx,
2446                apr_pool_t *pool)
2447 {
2448   return svn_client_cat2(out, path_or_url, revision, revision,
2449                          ctx, pool);
2450 }
2451
2452 /*** From checkout.c ***/
2453 svn_error_t *
2454 svn_client_checkout2(svn_revnum_t *result_rev,
2455                      const char *URL,
2456                      const char *path,
2457                      const svn_opt_revision_t *peg_revision,
2458                      const svn_opt_revision_t *revision,
2459                      svn_boolean_t recurse,
2460                      svn_boolean_t ignore_externals,
2461                      svn_client_ctx_t *ctx,
2462                      apr_pool_t *pool)
2463 {
2464   return svn_error_trace(svn_client_checkout3(result_rev, URL, path,
2465                                         peg_revision, revision,
2466                                         SVN_DEPTH_INFINITY_OR_FILES(recurse),
2467                                         ignore_externals, FALSE, ctx, pool));
2468 }
2469
2470 svn_error_t *
2471 svn_client_checkout(svn_revnum_t *result_rev,
2472                     const char *URL,
2473                     const char *path,
2474                     const svn_opt_revision_t *revision,
2475                     svn_boolean_t recurse,
2476                     svn_client_ctx_t *ctx,
2477                     apr_pool_t *pool)
2478 {
2479   svn_opt_revision_t peg_revision;
2480
2481   peg_revision.kind = svn_opt_revision_unspecified;
2482
2483   return svn_error_trace(svn_client_checkout2(result_rev, URL, path,
2484                                               &peg_revision, revision, recurse,
2485                                               FALSE, ctx, pool));
2486 }
2487
2488 /*** From info.c ***/
2489
2490 svn_info_t *
2491 svn_info_dup(const svn_info_t *info, apr_pool_t *pool)
2492 {
2493   svn_info_t *dupinfo = apr_palloc(pool, sizeof(*dupinfo));
2494
2495   /* Perform a trivial copy ... */
2496   *dupinfo = *info;
2497
2498   /* ...and then re-copy stuff that needs to be duped into our pool. */
2499   if (info->URL)
2500     dupinfo->URL = apr_pstrdup(pool, info->URL);
2501   if (info->repos_root_URL)
2502     dupinfo->repos_root_URL = apr_pstrdup(pool, info->repos_root_URL);
2503   if (info->repos_UUID)
2504     dupinfo->repos_UUID = apr_pstrdup(pool, info->repos_UUID);
2505   if (info->last_changed_author)
2506     dupinfo->last_changed_author = apr_pstrdup(pool,
2507                                                info->last_changed_author);
2508   if (info->lock)
2509     dupinfo->lock = svn_lock_dup(info->lock, pool);
2510   if (info->copyfrom_url)
2511     dupinfo->copyfrom_url = apr_pstrdup(pool, info->copyfrom_url);
2512   if (info->checksum)
2513     dupinfo->checksum = apr_pstrdup(pool, info->checksum);
2514   if (info->conflict_old)
2515     dupinfo->conflict_old = apr_pstrdup(pool, info->conflict_old);
2516   if (info->conflict_new)
2517     dupinfo->conflict_new = apr_pstrdup(pool, info->conflict_new);
2518   if (info->conflict_wrk)
2519     dupinfo->conflict_wrk = apr_pstrdup(pool, info->conflict_wrk);
2520   if (info->prejfile)
2521     dupinfo->prejfile = apr_pstrdup(pool, info->prejfile);
2522
2523   return dupinfo;
2524 }
2525
2526 /* Convert an svn_client_info2_t to an svn_info_t, doing shallow copies. */
2527 static svn_error_t *
2528 info_from_info2(svn_info_t **new_info,
2529                 svn_wc_context_t *wc_ctx,
2530                 const svn_client_info2_t *info2,
2531                 apr_pool_t *pool)
2532 {
2533   svn_info_t *info = apr_pcalloc(pool, sizeof(*info));
2534
2535   info->URL                 = info2->URL;
2536   /* Goofy backward compat handling for added nodes. */
2537   if (SVN_IS_VALID_REVNUM(info2->rev))
2538     info->rev               = info2->rev;
2539   else
2540     info->rev               = 0;
2541
2542   info->kind                = info2->kind;
2543   info->repos_root_URL      = info2->repos_root_URL;
2544   info->repos_UUID          = info2->repos_UUID;
2545   info->last_changed_rev    = info2->last_changed_rev;
2546   info->last_changed_date   = info2->last_changed_date;
2547   info->last_changed_author = info2->last_changed_author;
2548
2549   /* Stupid old structure has a non-const LOCK member. Sigh.  */
2550   info->lock                = (svn_lock_t *)info2->lock;
2551
2552   info->size64              = info2->size;
2553   if (info2->size == SVN_INVALID_FILESIZE)
2554     info->size               = SVN_INFO_SIZE_UNKNOWN;
2555   else if (((svn_filesize_t)(apr_size_t)info->size64) == info->size64)
2556     info->size               = (apr_size_t)info->size64;
2557   else /* >= 4GB */
2558     info->size               = SVN_INFO_SIZE_UNKNOWN;
2559
2560   if (info2->wc_info)
2561     {
2562       info->has_wc_info         = TRUE;
2563       info->schedule            = info2->wc_info->schedule;
2564       info->copyfrom_url        = info2->wc_info->copyfrom_url;
2565       info->copyfrom_rev        = info2->wc_info->copyfrom_rev;
2566       info->text_time           = info2->wc_info->recorded_time;
2567       info->prop_time           = 0;
2568       if (info2->wc_info->checksum
2569             && info2->wc_info->checksum->kind == svn_checksum_md5)
2570         info->checksum          = svn_checksum_to_cstring(
2571                                         info2->wc_info->checksum, pool);
2572       else
2573         info->checksum          = NULL;
2574       info->changelist          = info2->wc_info->changelist;
2575       info->depth               = info2->wc_info->depth;
2576
2577       if (info->depth == svn_depth_unknown && info->kind == svn_node_file)
2578         info->depth = svn_depth_infinity;
2579
2580       info->working_size64      = info2->wc_info->recorded_size;
2581       if (((svn_filesize_t)(apr_size_t)info->working_size64) == info->working_size64)
2582         info->working_size       = (apr_size_t)info->working_size64;
2583       else /* >= 4GB */
2584         info->working_size       = SVN_INFO_SIZE_UNKNOWN;
2585     }
2586   else
2587     {
2588       info->has_wc_info           = FALSE;
2589       info->working_size          = SVN_INFO_SIZE_UNKNOWN;
2590       info->working_size64        = SVN_INVALID_FILESIZE;
2591       info->depth                 = svn_depth_unknown;
2592     }
2593
2594   /* Populate conflict fields. */
2595   if (info2->wc_info && info2->wc_info->conflicts)
2596     {
2597       int i;
2598
2599       for (i = 0; i < info2->wc_info->conflicts->nelts; i++)
2600         {
2601           const svn_wc_conflict_description2_t *conflict
2602                               = APR_ARRAY_IDX(info2->wc_info->conflicts, i,
2603                                     const svn_wc_conflict_description2_t *);
2604
2605           /* ### Not really sure what we should do if we get multiple
2606              ### conflicts of the same type. */
2607           switch (conflict->kind)
2608             {
2609               case svn_wc_conflict_kind_tree:
2610                 info->tree_conflict = svn_wc__cd2_to_cd(conflict, pool);
2611                 break;
2612
2613               case svn_wc_conflict_kind_text:
2614                 info->conflict_old = conflict->base_abspath;
2615                 info->conflict_new = conflict->my_abspath;
2616                 info->conflict_wrk = conflict->their_abspath;
2617                 break;
2618
2619               case svn_wc_conflict_kind_property:
2620                 info->prejfile = conflict->their_abspath;
2621                 break;
2622             }
2623         }
2624     }
2625
2626   if (info2->wc_info && info2->wc_info->checksum)
2627     {
2628       const svn_checksum_t *md5_checksum;
2629
2630       SVN_ERR(svn_wc__node_get_md5_from_sha1(&md5_checksum,
2631                                              wc_ctx,
2632                                              info2->wc_info->wcroot_abspath,
2633                                              info2->wc_info->checksum,
2634                                              pool, pool));
2635
2636       info->checksum = svn_checksum_to_cstring(md5_checksum, pool);
2637     }
2638
2639   *new_info = info;
2640   return SVN_NO_ERROR;
2641 }
2642
2643 struct info_to_relpath_baton
2644 {
2645   const char *anchor_abspath;
2646   const char *anchor_relpath;
2647   svn_info_receiver_t info_receiver;
2648   void *info_baton;
2649   svn_wc_context_t *wc_ctx;
2650 };
2651
2652 static svn_error_t *
2653 info_receiver_relpath_wrapper(void *baton,
2654                               const char *abspath_or_url,
2655                               const svn_client_info2_t *info2,
2656                               apr_pool_t *scratch_pool)
2657 {
2658   struct info_to_relpath_baton *rb = baton;
2659   const char *path = abspath_or_url;
2660   svn_info_t *info;
2661
2662   if (rb->anchor_relpath &&
2663       svn_dirent_is_ancestor(rb->anchor_abspath, abspath_or_url))
2664     {
2665       path = svn_dirent_join(rb->anchor_relpath,
2666                              svn_dirent_skip_ancestor(rb->anchor_abspath,
2667                                                       abspath_or_url),
2668                              scratch_pool);
2669     }
2670
2671   SVN_ERR(info_from_info2(&info, rb->wc_ctx, info2, scratch_pool));
2672
2673   SVN_ERR(rb->info_receiver(rb->info_baton,
2674                             path,
2675                             info,
2676                             scratch_pool));
2677
2678   return SVN_NO_ERROR;
2679 }
2680
2681 svn_error_t *
2682 svn_client_info2(const char *path_or_url,
2683                  const svn_opt_revision_t *peg_revision,
2684                  const svn_opt_revision_t *revision,
2685                  svn_info_receiver_t receiver,
2686                  void *receiver_baton,
2687                  svn_depth_t depth,
2688                  const apr_array_header_t *changelists,
2689                  svn_client_ctx_t *ctx,
2690                  apr_pool_t *pool)
2691 {
2692   struct info_to_relpath_baton rb;
2693   const char *abspath_or_url = path_or_url;
2694
2695   rb.anchor_relpath = NULL;
2696   rb.info_receiver = receiver;
2697   rb.info_baton = receiver_baton;
2698   rb.wc_ctx = ctx->wc_ctx;
2699
2700   if (!svn_path_is_url(path_or_url))
2701     {
2702       SVN_ERR(svn_dirent_get_absolute(&abspath_or_url, path_or_url, pool));
2703       rb.anchor_abspath = abspath_or_url;
2704       rb.anchor_relpath = path_or_url;
2705     }
2706
2707   SVN_ERR(svn_client_info3(abspath_or_url,
2708                            peg_revision,
2709                            revision,
2710                            depth,
2711                            FALSE, TRUE,
2712                            changelists,
2713                            info_receiver_relpath_wrapper,
2714                            &rb,
2715                            ctx,
2716                            pool));
2717
2718   return SVN_NO_ERROR;
2719 }
2720
2721 svn_error_t *
2722 svn_client_info(const char *path_or_url,
2723                 const svn_opt_revision_t *peg_revision,
2724                 const svn_opt_revision_t *revision,
2725                 svn_info_receiver_t receiver,
2726                 void *receiver_baton,
2727                 svn_boolean_t recurse,
2728                 svn_client_ctx_t *ctx,
2729                 apr_pool_t *pool)
2730 {
2731   return svn_client_info2(path_or_url, peg_revision, revision,
2732                           receiver, receiver_baton,
2733                           SVN_DEPTH_INFINITY_OR_EMPTY(recurse),
2734                           NULL, ctx, pool);
2735 }
2736
2737 /*** From resolved.c ***/
2738 svn_error_t *
2739 svn_client_resolved(const char *path,
2740                     svn_boolean_t recursive,
2741                     svn_client_ctx_t *ctx,
2742                     apr_pool_t *pool)
2743 {
2744   svn_depth_t depth = SVN_DEPTH_INFINITY_OR_EMPTY(recursive);
2745   return svn_client_resolve(path, depth,
2746                             svn_wc_conflict_choose_merged, ctx, pool);
2747 }
2748 /*** From revert.c ***/
2749 svn_error_t *
2750 svn_client_revert(const apr_array_header_t *paths,
2751                   svn_boolean_t recursive,
2752                   svn_client_ctx_t *ctx,
2753                   apr_pool_t *pool)
2754 {
2755   return svn_client_revert2(paths, SVN_DEPTH_INFINITY_OR_EMPTY(recursive),
2756                             NULL, ctx, pool);
2757 }
2758
2759 /*** From ra.c ***/
2760 svn_error_t *
2761 svn_client_open_ra_session(svn_ra_session_t **session,
2762                            const char *url,
2763                            svn_client_ctx_t *ctx,
2764                            apr_pool_t *pool)
2765 {
2766   return svn_error_trace(
2767              svn_client_open_ra_session2(session, url,
2768                                          NULL, ctx,
2769                                          pool, pool));
2770 }
2771
2772 svn_error_t *
2773 svn_client_uuid_from_url(const char **uuid,
2774                          const char *url,
2775                          svn_client_ctx_t *ctx,
2776                          apr_pool_t *pool)
2777 {
2778   svn_error_t *err;
2779   apr_pool_t *subpool = svn_pool_create(pool);
2780
2781   err = svn_client_get_repos_root(NULL, uuid, url,
2782                                   ctx, pool, subpool);
2783   /* destroy the RA session */
2784   svn_pool_destroy(subpool);
2785
2786   return svn_error_trace(err);;
2787 }
2788
2789 svn_error_t *
2790 svn_client_uuid_from_path2(const char **uuid,
2791                            const char *local_abspath,
2792                            svn_client_ctx_t *ctx,
2793                            apr_pool_t *result_pool,
2794                            apr_pool_t *scratch_pool)
2795 {
2796   return svn_error_trace(
2797       svn_client_get_repos_root(NULL, uuid,
2798                                 local_abspath, ctx,
2799                                 result_pool, scratch_pool));
2800 }
2801
2802 svn_error_t *
2803 svn_client_uuid_from_path(const char **uuid,
2804                           const char *path,
2805                           svn_wc_adm_access_t *adm_access,
2806                           svn_client_ctx_t *ctx,
2807                           apr_pool_t *pool)
2808 {
2809   const char *local_abspath;
2810
2811   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
2812   return svn_error_trace(
2813     svn_client_uuid_from_path2(uuid, local_abspath, ctx, pool, pool));
2814 }
2815
2816 /*** From url.c ***/
2817 svn_error_t *
2818 svn_client_root_url_from_path(const char **url,
2819                               const char *path_or_url,
2820                               svn_client_ctx_t *ctx,
2821                               apr_pool_t *pool)
2822 {
2823   apr_pool_t *subpool = svn_pool_create(pool);
2824   svn_error_t *err;
2825   if (!svn_path_is_url(path_or_url))
2826     SVN_ERR(svn_dirent_get_absolute(&path_or_url, path_or_url, pool));
2827
2828   err = svn_client_get_repos_root(url, NULL, path_or_url,
2829                                   ctx, pool, subpool);
2830
2831   /* close ra session */
2832   svn_pool_destroy(subpool);
2833   return svn_error_trace(err);
2834 }
2835
2836 svn_error_t *
2837 svn_client_url_from_path(const char **url,
2838                          const char *path_or_url,
2839                          apr_pool_t *pool)
2840 {
2841   svn_client_ctx_t *ctx;
2842
2843   SVN_ERR(svn_client_create_context(&ctx, pool));
2844
2845   return svn_client_url_from_path2(url, path_or_url, ctx, pool, pool);
2846 }
2847
2848 /*** From mergeinfo.c ***/
2849 svn_error_t *
2850 svn_client_mergeinfo_log(svn_boolean_t finding_merged,
2851                          const char *target_path_or_url,
2852                          const svn_opt_revision_t *target_peg_revision,
2853                          const char *source_path_or_url,
2854                          const svn_opt_revision_t *source_peg_revision,
2855                          svn_log_entry_receiver_t receiver,
2856                          void *receiver_baton,
2857                          svn_boolean_t discover_changed_paths,
2858                          svn_depth_t depth,
2859                          const apr_array_header_t *revprops,
2860                          svn_client_ctx_t *ctx,
2861                          apr_pool_t *scratch_pool)
2862 {
2863   svn_opt_revision_t start_revision, end_revision;
2864
2865   start_revision.kind = svn_opt_revision_unspecified;
2866   end_revision.kind = svn_opt_revision_unspecified;
2867
2868   return svn_client_mergeinfo_log2(finding_merged,
2869                                    target_path_or_url, target_peg_revision,
2870                                    source_path_or_url, source_peg_revision,
2871                                    &start_revision, &end_revision,
2872                                    receiver, receiver_baton,
2873                                    discover_changed_paths, depth, revprops,
2874                                    ctx, scratch_pool);
2875 }
2876
2877 svn_error_t *
2878 svn_client_mergeinfo_log_merged(const char *path_or_url,
2879                                 const svn_opt_revision_t *peg_revision,
2880                                 const char *merge_source_path_or_url,
2881                                 const svn_opt_revision_t *src_peg_revision,
2882                                 svn_log_entry_receiver_t log_receiver,
2883                                 void *log_receiver_baton,
2884                                 svn_boolean_t discover_changed_paths,
2885                                 const apr_array_header_t *revprops,
2886                                 svn_client_ctx_t *ctx,
2887                                 apr_pool_t *pool)
2888 {
2889   return svn_client_mergeinfo_log(TRUE, path_or_url, peg_revision,
2890                                   merge_source_path_or_url,
2891                                   src_peg_revision,
2892                                   log_receiver, log_receiver_baton,
2893                                   discover_changed_paths,
2894                                   svn_depth_empty, revprops, ctx,
2895                                   pool);
2896 }
2897
2898 svn_error_t *
2899 svn_client_mergeinfo_log_eligible(const char *path_or_url,
2900                                   const svn_opt_revision_t *peg_revision,
2901                                   const char *merge_source_path_or_url,
2902                                   const svn_opt_revision_t *src_peg_revision,
2903                                   svn_log_entry_receiver_t log_receiver,
2904                                   void *log_receiver_baton,
2905                                   svn_boolean_t discover_changed_paths,
2906                                   const apr_array_header_t *revprops,
2907                                   svn_client_ctx_t *ctx,
2908                                   apr_pool_t *pool)
2909 {
2910   return svn_client_mergeinfo_log(FALSE, path_or_url, peg_revision,
2911                                   merge_source_path_or_url,
2912                                   src_peg_revision,
2913                                   log_receiver, log_receiver_baton,
2914                                   discover_changed_paths,
2915                                   svn_depth_empty, revprops, ctx,
2916                                   pool);
2917 }
2918
2919 /*** From relocate.c ***/
2920 svn_error_t *
2921 svn_client_relocate(const char *path,
2922                     const char *from_prefix,
2923                     const char *to_prefix,
2924                     svn_boolean_t recurse,
2925                     svn_client_ctx_t *ctx,
2926                     apr_pool_t *pool)
2927 {
2928   if (! recurse)
2929     SVN_ERR(svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
2930                              _("Non-recursive relocation not supported")));
2931   return svn_client_relocate2(path, from_prefix, to_prefix, TRUE, ctx, pool);
2932 }
2933
2934 /*** From util.c ***/
2935 svn_error_t *
2936 svn_client_commit_item_create(const svn_client_commit_item3_t **item,
2937                               apr_pool_t *pool)
2938 {
2939   *item = svn_client_commit_item3_create(pool);
2940   return SVN_NO_ERROR;
2941 }
2942
2943 svn_client_commit_item2_t *
2944 svn_client_commit_item2_dup(const svn_client_commit_item2_t *item,
2945                             apr_pool_t *pool)
2946 {
2947   svn_client_commit_item2_t *new_item = apr_palloc(pool, sizeof(*new_item));
2948
2949   *new_item = *item;
2950
2951   if (new_item->path)
2952     new_item->path = apr_pstrdup(pool, new_item->path);
2953
2954   if (new_item->url)
2955     new_item->url = apr_pstrdup(pool, new_item->url);
2956
2957   if (new_item->copyfrom_url)
2958     new_item->copyfrom_url = apr_pstrdup(pool, new_item->copyfrom_url);
2959
2960   if (new_item->wcprop_changes)
2961     new_item->wcprop_changes = svn_prop_array_dup(new_item->wcprop_changes,
2962                                                   pool);
2963
2964   return new_item;
2965 }
2966