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