]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/subversion/subversion/libsvn_wc/deprecated.c
MFC r275385 (by bapt):
[FreeBSD/stable/10.git] / contrib / subversion / subversion / libsvn_wc / deprecated.c
1 /*
2  * deprecated.c:  holding file for all deprecated APIs.
3  *                "we can't lose 'em, but we can shun 'em!"
4  *
5  * ====================================================================
6  *    Licensed to the Apache Software Foundation (ASF) under one
7  *    or more contributor license agreements.  See the NOTICE file
8  *    distributed with this work for additional information
9  *    regarding copyright ownership.  The ASF licenses this file
10  *    to you under the Apache License, Version 2.0 (the
11  *    "License"); you may not use this file except in compliance
12  *    with the License.  You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  *    Unless required by applicable law or agreed to in writing,
17  *    software distributed under the License is distributed on an
18  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19  *    KIND, either express or implied.  See the License for the
20  *    specific language governing permissions and limitations
21  *    under the License.
22  * ====================================================================
23  */
24
25 /* We define this here to remove any further warnings about the usage of
26    deprecated functions in this file. */
27 #define SVN_DEPRECATED
28
29 #include <apr_md5.h>
30
31 #include "svn_wc.h"
32 #include "svn_subst.h"
33 #include "svn_pools.h"
34 #include "svn_props.h"
35 #include "svn_hash.h"
36 #include "svn_time.h"
37 #include "svn_dirent_uri.h"
38 #include "svn_path.h"
39
40 #include "private/svn_subr_private.h"
41 #include "private/svn_wc_private.h"
42
43 #include "wc.h"
44 #include "entries.h"
45 #include "lock.h"
46 #include "props.h"
47 #include "translate.h"
48 #include "workqueue.h"
49
50 #include "svn_private_config.h"
51
52 /* baton for traversal_info_update */
53 struct traversal_info_update_baton
54 {
55   struct svn_wc_traversal_info_t *traversal;
56   svn_wc__db_t *db;
57 };
58
59 /* Helper for updating svn_wc_traversal_info_t structures
60  * Implements svn_wc_external_update_t */
61 static svn_error_t *
62 traversal_info_update(void *baton,
63                       const char *local_abspath,
64                       const svn_string_t *old_val,
65                       const svn_string_t *new_val,
66                       svn_depth_t depth,
67                       apr_pool_t *scratch_pool)
68 {
69   const char *dup_path;
70   svn_wc_adm_access_t *adm_access;
71   struct traversal_info_update_baton *ub = baton;
72   apr_pool_t *dup_pool = ub->traversal->pool;
73   const char *dup_val = NULL;
74
75   /* We make the abspath relative by retrieving the access baton
76      for the specific directory */
77   adm_access = svn_wc__adm_retrieve_internal2(ub->db, local_abspath,
78                                               scratch_pool);
79
80   if (adm_access)
81     dup_path = apr_pstrdup(dup_pool, svn_wc_adm_access_path(adm_access));
82   else
83     dup_path = apr_pstrdup(dup_pool, local_abspath);
84
85   if (old_val)
86     {
87       dup_val = apr_pstrmemdup(dup_pool, old_val->data, old_val->len);
88
89       svn_hash_sets(ub->traversal->externals_old, dup_path, dup_val);
90     }
91
92   if (new_val)
93     {
94       /* In most cases the value is identical */
95       if (old_val != new_val)
96         dup_val = apr_pstrmemdup(dup_pool, new_val->data, new_val->len);
97
98       svn_hash_sets(ub->traversal->externals_new, dup_path, dup_val);
99     }
100
101   svn_hash_sets(ub->traversal->depths, dup_path, svn_depth_to_word(depth));
102
103   return SVN_NO_ERROR;
104 }
105
106 /* Helper for functions that used to gather traversal_info */
107 static svn_error_t *
108 gather_traversal_info(svn_wc_context_t *wc_ctx,
109                       const char *local_abspath,
110                       const char *path,
111                       svn_depth_t depth,
112                       struct svn_wc_traversal_info_t *traversal_info,
113                       svn_boolean_t gather_as_old,
114                       svn_boolean_t gather_as_new,
115                       apr_pool_t *scratch_pool)
116 {
117   apr_hash_t *externals;
118   apr_hash_t *ambient_depths;
119   apr_hash_index_t *hi;
120
121   SVN_ERR(svn_wc__externals_gather_definitions(&externals, &ambient_depths,
122                                                wc_ctx, local_abspath,
123                                                depth,
124                                                scratch_pool, scratch_pool));
125
126   for (hi = apr_hash_first(scratch_pool, externals);
127        hi;
128        hi = apr_hash_next(hi))
129     {
130       const char *node_abspath = apr_hash_this_key(hi);
131       const char *relpath;
132
133       relpath = svn_dirent_join(path,
134                                 svn_dirent_skip_ancestor(local_abspath,
135                                                          node_abspath),
136                                 traversal_info->pool);
137
138       if (gather_as_old)
139         svn_hash_sets(traversal_info->externals_old, relpath,
140                       apr_hash_this_val(hi));
141
142       if (gather_as_new)
143         svn_hash_sets(traversal_info->externals_new, relpath,
144                       apr_hash_this_val(hi));
145
146       svn_hash_sets(traversal_info->depths, relpath,
147                     svn_hash_gets(ambient_depths, node_abspath));
148     }
149
150   return SVN_NO_ERROR;
151 }
152
153 \f
154 /*** From adm_crawler.c ***/
155
156 svn_error_t *
157 svn_wc_crawl_revisions4(const char *path,
158                         svn_wc_adm_access_t *adm_access,
159                         const svn_ra_reporter3_t *reporter,
160                         void *report_baton,
161                         svn_boolean_t restore_files,
162                         svn_depth_t depth,
163                         svn_boolean_t honor_depth_exclude,
164                         svn_boolean_t depth_compatibility_trick,
165                         svn_boolean_t use_commit_times,
166                         svn_wc_notify_func2_t notify_func,
167                         void *notify_baton,
168                         svn_wc_traversal_info_t *traversal_info,
169                         apr_pool_t *pool)
170 {
171   svn_wc_context_t *wc_ctx;
172   svn_wc__db_t *wc_db = svn_wc__adm_get_db(adm_access);
173   const char *local_abspath;
174
175   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, wc_db, pool));
176   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
177
178   SVN_ERR(svn_wc_crawl_revisions5(wc_ctx,
179                                   local_abspath,
180                                   reporter,
181                                   report_baton,
182                                   restore_files,
183                                   depth,
184                                   honor_depth_exclude,
185                                   depth_compatibility_trick,
186                                   use_commit_times,
187                                   NULL /* cancel_func */,
188                                   NULL /* cancel_baton */,
189                                   notify_func,
190                                   notify_baton,
191                                   pool));
192
193   if (traversal_info)
194     SVN_ERR(gather_traversal_info(wc_ctx, local_abspath, path, depth,
195                                   traversal_info, TRUE, FALSE, pool));
196
197   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
198 }
199
200 /*** Compatibility wrapper: turns an svn_ra_reporter2_t into an
201      svn_ra_reporter3_t.
202
203      This code looks like it duplicates code in libsvn_ra/ra_loader.c,
204      but it does not.  That code makes an new thing look like an old
205      thing; this code makes an old thing look like a new thing. ***/
206
207 struct wrap_3to2_report_baton {
208   const svn_ra_reporter2_t *reporter;
209   void *baton;
210 };
211
212 /* */
213 static svn_error_t *wrap_3to2_set_path(void *report_baton,
214                                        const char *path,
215                                        svn_revnum_t revision,
216                                        svn_depth_t depth,
217                                        svn_boolean_t start_empty,
218                                        const char *lock_token,
219                                        apr_pool_t *pool)
220 {
221   struct wrap_3to2_report_baton *wrb = report_baton;
222
223   return wrb->reporter->set_path(wrb->baton, path, revision, start_empty,
224                                  lock_token, pool);
225 }
226
227 /* */
228 static svn_error_t *wrap_3to2_delete_path(void *report_baton,
229                                           const char *path,
230                                           apr_pool_t *pool)
231 {
232   struct wrap_3to2_report_baton *wrb = report_baton;
233
234   return wrb->reporter->delete_path(wrb->baton, path, pool);
235 }
236
237 /* */
238 static svn_error_t *wrap_3to2_link_path(void *report_baton,
239                                         const char *path,
240                                         const char *url,
241                                         svn_revnum_t revision,
242                                         svn_depth_t depth,
243                                         svn_boolean_t start_empty,
244                                         const char *lock_token,
245                                         apr_pool_t *pool)
246 {
247   struct wrap_3to2_report_baton *wrb = report_baton;
248
249   return wrb->reporter->link_path(wrb->baton, path, url, revision,
250                                   start_empty, lock_token, pool);
251 }
252
253 /* */
254 static svn_error_t *wrap_3to2_finish_report(void *report_baton,
255                                             apr_pool_t *pool)
256 {
257   struct wrap_3to2_report_baton *wrb = report_baton;
258
259   return wrb->reporter->finish_report(wrb->baton, pool);
260 }
261
262 /* */
263 static svn_error_t *wrap_3to2_abort_report(void *report_baton,
264                                            apr_pool_t *pool)
265 {
266   struct wrap_3to2_report_baton *wrb = report_baton;
267
268   return wrb->reporter->abort_report(wrb->baton, pool);
269 }
270
271 static const svn_ra_reporter3_t wrap_3to2_reporter = {
272   wrap_3to2_set_path,
273   wrap_3to2_delete_path,
274   wrap_3to2_link_path,
275   wrap_3to2_finish_report,
276   wrap_3to2_abort_report
277 };
278
279 svn_error_t *
280 svn_wc_crawl_revisions3(const char *path,
281                         svn_wc_adm_access_t *adm_access,
282                         const svn_ra_reporter3_t *reporter,
283                         void *report_baton,
284                         svn_boolean_t restore_files,
285                         svn_depth_t depth,
286                         svn_boolean_t depth_compatibility_trick,
287                         svn_boolean_t use_commit_times,
288                         svn_wc_notify_func2_t notify_func,
289                         void *notify_baton,
290                         svn_wc_traversal_info_t *traversal_info,
291                         apr_pool_t *pool)
292 {
293   return svn_wc_crawl_revisions4(path,
294                                  adm_access,
295                                  reporter, report_baton,
296                                  restore_files,
297                                  depth,
298                                  FALSE,
299                                  depth_compatibility_trick,
300                                  use_commit_times,
301                                  notify_func,
302                                  notify_baton,
303                                  traversal_info,
304                                  pool);
305 }
306
307 svn_error_t *
308 svn_wc_crawl_revisions2(const char *path,
309                         svn_wc_adm_access_t *adm_access,
310                         const svn_ra_reporter2_t *reporter,
311                         void *report_baton,
312                         svn_boolean_t restore_files,
313                         svn_boolean_t recurse,
314                         svn_boolean_t use_commit_times,
315                         svn_wc_notify_func2_t notify_func,
316                         void *notify_baton,
317                         svn_wc_traversal_info_t *traversal_info,
318                         apr_pool_t *pool)
319 {
320   struct wrap_3to2_report_baton wrb;
321   wrb.reporter = reporter;
322   wrb.baton = report_baton;
323
324   return svn_wc_crawl_revisions3(path,
325                                  adm_access,
326                                  &wrap_3to2_reporter, &wrb,
327                                  restore_files,
328                                  SVN_DEPTH_INFINITY_OR_FILES(recurse),
329                                  FALSE,
330                                  use_commit_times,
331                                  notify_func,
332                                  notify_baton,
333                                  traversal_info,
334                                  pool);
335 }
336
337
338 /* Baton for compat_call_notify_func below.  */
339 struct compat_notify_baton_t {
340   /* Wrapped func/baton. */
341   svn_wc_notify_func_t func;
342   void *baton;
343 };
344
345
346 /* Implements svn_wc_notify_func2_t.  Call BATON->func (BATON is of type
347    svn_wc__compat_notify_baton_t), passing BATON->baton and the appropriate
348    arguments from NOTIFY.  */
349 static void
350 compat_call_notify_func(void *baton,
351                         const svn_wc_notify_t *n,
352                         apr_pool_t *pool)
353 {
354   struct compat_notify_baton_t *nb = baton;
355
356   if (nb->func)
357     (*nb->func)(nb->baton, n->path, n->action, n->kind, n->mime_type,
358                 n->content_state, n->prop_state, n->revision);
359 }
360
361
362 /*** Compatibility wrapper: turns an svn_ra_reporter_t into an
363      svn_ra_reporter2_t.
364
365      This code looks like it duplicates code in libsvn_ra/ra_loader.c,
366      but it does not.  That code makes an new thing look like an old
367      thing; this code makes an old thing look like a new thing. ***/
368
369 struct wrap_2to1_report_baton {
370   const svn_ra_reporter_t *reporter;
371   void *baton;
372 };
373
374 /* */
375 static svn_error_t *wrap_2to1_set_path(void *report_baton,
376                                        const char *path,
377                                        svn_revnum_t revision,
378                                        svn_boolean_t start_empty,
379                                        const char *lock_token,
380                                        apr_pool_t *pool)
381 {
382   struct wrap_2to1_report_baton *wrb = report_baton;
383
384   return wrb->reporter->set_path(wrb->baton, path, revision, start_empty,
385                                  pool);
386 }
387
388 /* */
389 static svn_error_t *wrap_2to1_delete_path(void *report_baton,
390                                           const char *path,
391                                           apr_pool_t *pool)
392 {
393   struct wrap_2to1_report_baton *wrb = report_baton;
394
395   return wrb->reporter->delete_path(wrb->baton, path, pool);
396 }
397
398 /* */
399 static svn_error_t *wrap_2to1_link_path(void *report_baton,
400                                         const char *path,
401                                         const char *url,
402                                         svn_revnum_t revision,
403                                         svn_boolean_t start_empty,
404                                         const char *lock_token,
405                                         apr_pool_t *pool)
406 {
407   struct wrap_2to1_report_baton *wrb = report_baton;
408
409   return wrb->reporter->link_path(wrb->baton, path, url, revision,
410                                   start_empty, pool);
411 }
412
413 /* */
414 static svn_error_t *wrap_2to1_finish_report(void *report_baton,
415                                             apr_pool_t *pool)
416 {
417   struct wrap_2to1_report_baton *wrb = report_baton;
418
419   return wrb->reporter->finish_report(wrb->baton, pool);
420 }
421
422 /* */
423 static svn_error_t *wrap_2to1_abort_report(void *report_baton,
424                                            apr_pool_t *pool)
425 {
426   struct wrap_2to1_report_baton *wrb = report_baton;
427
428   return wrb->reporter->abort_report(wrb->baton, pool);
429 }
430
431 static const svn_ra_reporter2_t wrap_2to1_reporter = {
432   wrap_2to1_set_path,
433   wrap_2to1_delete_path,
434   wrap_2to1_link_path,
435   wrap_2to1_finish_report,
436   wrap_2to1_abort_report
437 };
438
439 svn_error_t *
440 svn_wc_crawl_revisions(const char *path,
441                        svn_wc_adm_access_t *adm_access,
442                        const svn_ra_reporter_t *reporter,
443                        void *report_baton,
444                        svn_boolean_t restore_files,
445                        svn_boolean_t recurse,
446                        svn_boolean_t use_commit_times,
447                        svn_wc_notify_func_t notify_func,
448                        void *notify_baton,
449                        svn_wc_traversal_info_t *traversal_info,
450                        apr_pool_t *pool)
451 {
452   struct wrap_2to1_report_baton wrb;
453   struct compat_notify_baton_t nb;
454
455   wrb.reporter = reporter;
456   wrb.baton = report_baton;
457
458   nb.func = notify_func;
459   nb.baton = notify_baton;
460
461   return svn_wc_crawl_revisions2(path, adm_access, &wrap_2to1_reporter, &wrb,
462                                  restore_files, recurse, use_commit_times,
463                                  compat_call_notify_func, &nb,
464                                  traversal_info,
465                                  pool);
466 }
467
468 svn_error_t *
469 svn_wc_transmit_text_deltas2(const char **tempfile,
470                              unsigned char digest[],
471                              const char *path,
472                              svn_wc_adm_access_t *adm_access,
473                              svn_boolean_t fulltext,
474                              const svn_delta_editor_t *editor,
475                              void *file_baton,
476                              apr_pool_t *pool)
477 {
478   const char *local_abspath;
479   svn_wc_context_t *wc_ctx;
480   const svn_checksum_t *new_text_base_md5_checksum;
481
482   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
483   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
484                                          svn_wc__adm_get_db(adm_access),
485                                          pool));
486
487   SVN_ERR(svn_wc__internal_transmit_text_deltas(tempfile,
488                                                 (digest
489                                                  ? &new_text_base_md5_checksum
490                                                  : NULL),
491                                                 NULL, wc_ctx->db,
492                                                 local_abspath, fulltext,
493                                                 editor, file_baton,
494                                                 pool, pool));
495
496   if (digest)
497     memcpy(digest, new_text_base_md5_checksum->digest, APR_MD5_DIGESTSIZE);
498
499   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
500 }
501
502 svn_error_t *
503 svn_wc_transmit_text_deltas(const char *path,
504                             svn_wc_adm_access_t *adm_access,
505                             svn_boolean_t fulltext,
506                             const svn_delta_editor_t *editor,
507                             void *file_baton,
508                             const char **tempfile,
509                             apr_pool_t *pool)
510 {
511   return svn_wc_transmit_text_deltas2(tempfile, NULL, path, adm_access,
512                                       fulltext, editor, file_baton, pool);
513 }
514
515 svn_error_t *
516 svn_wc_transmit_prop_deltas(const char *path,
517                             svn_wc_adm_access_t *adm_access,
518                             const svn_wc_entry_t *entry,
519                             const svn_delta_editor_t *editor,
520                             void *baton,
521                             const char **tempfile,
522                             apr_pool_t *pool)
523 {
524   const char *local_abspath;
525   svn_wc_context_t *wc_ctx;
526
527   if (tempfile)
528     *tempfile = NULL;
529
530   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
531   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
532                                          svn_wc__adm_get_db(adm_access),
533                                          pool));
534
535   SVN_ERR(svn_wc_transmit_prop_deltas2(wc_ctx, local_abspath, editor, baton,
536                                        pool));
537
538   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
539 }
540
541 /*** From adm_files.c ***/
542 svn_error_t *
543 svn_wc_ensure_adm3(const char *path,
544                    const char *uuid,
545                    const char *url,
546                    const char *repos,
547                    svn_revnum_t revision,
548                    svn_depth_t depth,
549                    apr_pool_t *pool)
550 {
551   const char *local_abspath;
552   svn_wc_context_t *wc_ctx;
553
554   if (uuid == NULL)
555     return svn_error_create(SVN_ERR_BAD_UUID, NULL, NULL);
556   if (repos == NULL)
557     return svn_error_create(SVN_ERR_BAD_URL, NULL, NULL);
558
559   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
560   SVN_ERR(svn_wc_context_create(&wc_ctx, NULL /* config */, pool, pool));
561
562   SVN_ERR(svn_wc_ensure_adm4(wc_ctx, local_abspath, url, repos, uuid, revision,
563                              depth, pool));
564
565   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
566 }
567
568 svn_error_t *
569 svn_wc_ensure_adm2(const char *path,
570                    const char *uuid,
571                    const char *url,
572                    const char *repos,
573                    svn_revnum_t revision,
574                    apr_pool_t *pool)
575 {
576   return svn_wc_ensure_adm3(path, uuid, url, repos, revision,
577                             svn_depth_infinity, pool);
578 }
579
580
581 svn_error_t *
582 svn_wc_ensure_adm(const char *path,
583                   const char *uuid,
584                   const char *url,
585                   svn_revnum_t revision,
586                   apr_pool_t *pool)
587 {
588   return svn_wc_ensure_adm2(path, uuid, url, NULL, revision, pool);
589 }
590
591 svn_error_t *
592 svn_wc_create_tmp_file(apr_file_t **fp,
593                        const char *path,
594                        svn_boolean_t delete_on_close,
595                        apr_pool_t *pool)
596 {
597   return svn_wc_create_tmp_file2(fp, NULL, path,
598                                  delete_on_close
599                                  ? svn_io_file_del_on_close
600                                  : svn_io_file_del_none,
601                                  pool);
602 }
603
604 svn_error_t *
605 svn_wc_create_tmp_file2(apr_file_t **fp,
606                         const char **new_name,
607                         const char *path,
608                         svn_io_file_del_t delete_when,
609                         apr_pool_t *pool)
610 {
611   svn_wc_context_t *wc_ctx;
612   const char *local_abspath;
613   const char *temp_dir;
614   svn_error_t *err;
615
616   SVN_ERR_ASSERT(fp || new_name);
617
618   SVN_ERR(svn_wc_context_create(&wc_ctx, NULL /* config */, pool, pool));
619
620   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
621   err = svn_wc__get_tmpdir(&temp_dir, wc_ctx, local_abspath, pool, pool);
622   err = svn_error_compose_create(err, svn_wc_context_destroy(wc_ctx));
623   if (err)
624     return svn_error_trace(err);
625
626   SVN_ERR(svn_io_open_unique_file3(fp, new_name, temp_dir,
627                                    delete_when, pool, pool));
628
629   return SVN_NO_ERROR;
630 }
631
632
633 /*** From adm_ops.c ***/
634 svn_error_t *
635 svn_wc_get_pristine_contents(svn_stream_t **contents,
636                              const char *path,
637                              apr_pool_t *result_pool,
638                              apr_pool_t *scratch_pool)
639 {
640   svn_wc_context_t *wc_ctx;
641   const char *local_abspath;
642
643   SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, scratch_pool, scratch_pool));
644   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
645
646   SVN_ERR(svn_wc_get_pristine_contents2(contents,
647                                         wc_ctx,
648                                         local_abspath,
649                                         result_pool,
650                                         scratch_pool));
651
652   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
653 }
654
655 svn_error_t *
656 svn_wc_queue_committed3(svn_wc_committed_queue_t *queue,
657                         svn_wc_context_t *wc_ctx,
658                         const char *local_abspath,
659                         svn_boolean_t recurse,
660                         const apr_array_header_t *wcprop_changes,
661                         svn_boolean_t remove_lock,
662                         svn_boolean_t remove_changelist,
663                         const svn_checksum_t *sha1_checksum,
664                         apr_pool_t *scratch_pool)
665 {
666   return svn_error_trace(
667             svn_wc_queue_committed4(queue, wc_ctx, local_abspath,
668                                     recurse, TRUE /* is_committed */,
669                                     wcprop_changes, remove_lock,
670                                     remove_changelist, sha1_checksum,
671                                     scratch_pool));
672 }
673
674 svn_error_t *
675 svn_wc_queue_committed2(svn_wc_committed_queue_t *queue,
676                         const char *path,
677                         svn_wc_adm_access_t *adm_access,
678                         svn_boolean_t recurse,
679                         const apr_array_header_t *wcprop_changes,
680                         svn_boolean_t remove_lock,
681                         svn_boolean_t remove_changelist,
682                         const svn_checksum_t *md5_checksum,
683                         apr_pool_t *scratch_pool)
684 {
685   svn_wc_context_t *wc_ctx;
686   const char *local_abspath;
687   const svn_checksum_t *sha1_checksum = NULL;
688
689   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL,
690                                          svn_wc__adm_get_db(adm_access),
691                                          scratch_pool));
692   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
693
694   if (md5_checksum != NULL)
695     {
696       svn_error_t *err;
697       err = svn_wc__db_pristine_get_sha1(&sha1_checksum, wc_ctx->db,
698                                          local_abspath, md5_checksum,
699                                          svn_wc__get_committed_queue_pool(queue),
700                                          scratch_pool);
701
702       /* Don't fail on SHA1 not found */
703       if (err && err->apr_err == SVN_ERR_WC_DB_ERROR)
704         {
705           svn_error_clear(err);
706           sha1_checksum = NULL;
707         }
708       else
709         SVN_ERR(err);
710     }
711
712   SVN_ERR(svn_wc_queue_committed3(queue, wc_ctx, local_abspath, recurse,
713                                   wcprop_changes,
714                                   remove_lock, remove_changelist,
715                                   sha1_checksum, scratch_pool));
716
717   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
718 }
719
720 svn_error_t *
721 svn_wc_queue_committed(svn_wc_committed_queue_t **queue,
722                        const char *path,
723                        svn_wc_adm_access_t *adm_access,
724                        svn_boolean_t recurse,
725                        const apr_array_header_t *wcprop_changes,
726                        svn_boolean_t remove_lock,
727                        svn_boolean_t remove_changelist,
728                        const unsigned char *digest,
729                        apr_pool_t *pool)
730 {
731   const svn_checksum_t *md5_checksum;
732
733   if (digest)
734     md5_checksum = svn_checksum__from_digest_md5(
735                      digest, svn_wc__get_committed_queue_pool(*queue));
736   else
737     md5_checksum = NULL;
738
739   return svn_wc_queue_committed2(*queue, path, adm_access, recurse,
740                                  wcprop_changes, remove_lock,
741                                  remove_changelist, md5_checksum, pool);
742 }
743
744 svn_error_t *
745 svn_wc_process_committed_queue(svn_wc_committed_queue_t *queue,
746                                svn_wc_adm_access_t *adm_access,
747                                svn_revnum_t new_revnum,
748                                const char *rev_date,
749                                const char *rev_author,
750                                apr_pool_t *pool)
751 {
752   svn_wc_context_t *wc_ctx;
753
754   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL,
755                                          svn_wc__adm_get_db(adm_access),
756                                          pool));
757   SVN_ERR(svn_wc_process_committed_queue2(queue, wc_ctx, new_revnum,
758                                           rev_date, rev_author,
759                                           NULL, NULL, pool));
760   SVN_ERR(svn_wc_context_destroy(wc_ctx));
761
762   return SVN_NO_ERROR;
763 }
764
765 svn_error_t *
766 svn_wc_process_committed4(const char *path,
767                           svn_wc_adm_access_t *adm_access,
768                           svn_boolean_t recurse,
769                           svn_revnum_t new_revnum,
770                           const char *rev_date,
771                           const char *rev_author,
772                           const apr_array_header_t *wcprop_changes,
773                           svn_boolean_t remove_lock,
774                           svn_boolean_t remove_changelist,
775                           const unsigned char *digest,
776                           apr_pool_t *pool)
777 {
778   svn_wc__db_t *db = svn_wc__adm_get_db(adm_access);
779   const char *local_abspath;
780   const svn_checksum_t *md5_checksum;
781   const svn_checksum_t *sha1_checksum = NULL;
782   svn_wc_context_t *wc_ctx;
783   svn_wc_committed_queue_t *queue;
784
785   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
786   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, db, pool));
787
788   if (digest)
789     md5_checksum = svn_checksum__from_digest_md5(digest, pool);
790   else
791     md5_checksum = NULL;
792
793   if (md5_checksum != NULL)
794     {
795       svn_error_t *err;
796       err = svn_wc__db_pristine_get_sha1(&sha1_checksum, db,
797                                          local_abspath, md5_checksum,
798                                          pool, pool);
799
800       if (err && err->apr_err == SVN_ERR_WC_DB_ERROR)
801         {
802           svn_error_clear(err);
803           sha1_checksum = NULL;
804         }
805       else
806         SVN_ERR(err);
807     }
808
809   queue = svn_wc_committed_queue_create(pool);
810   SVN_ERR(svn_wc_queue_committed3(queue, wc_ctx, local_abspath, recurse,
811                                   wcprop_changes, remove_lock,
812                                   remove_changelist,
813                                   sha1_checksum /* or NULL if not modified
814                                                            or directory */,
815                                   pool));
816
817   SVN_ERR(svn_wc_process_committed_queue2(queue, wc_ctx,
818                                           new_revnum, rev_date, rev_author,
819                                           NULL, NULL /* cancel */,
820                                           pool));
821
822   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
823 }
824
825
826 svn_error_t *
827 svn_wc_process_committed3(const char *path,
828                           svn_wc_adm_access_t *adm_access,
829                           svn_boolean_t recurse,
830                           svn_revnum_t new_revnum,
831                           const char *rev_date,
832                           const char *rev_author,
833                           const apr_array_header_t *wcprop_changes,
834                           svn_boolean_t remove_lock,
835                           const unsigned char *digest,
836                           apr_pool_t *pool)
837 {
838   return svn_wc_process_committed4(path, adm_access, recurse, new_revnum,
839                                    rev_date, rev_author, wcprop_changes,
840                                    remove_lock, FALSE, digest, pool);
841 }
842
843 svn_error_t *
844 svn_wc_process_committed2(const char *path,
845                           svn_wc_adm_access_t *adm_access,
846                           svn_boolean_t recurse,
847                           svn_revnum_t new_revnum,
848                           const char *rev_date,
849                           const char *rev_author,
850                           const apr_array_header_t *wcprop_changes,
851                           svn_boolean_t remove_lock,
852                           apr_pool_t *pool)
853 {
854   return svn_wc_process_committed3(path, adm_access, recurse, new_revnum,
855                                    rev_date, rev_author, wcprop_changes,
856                                    remove_lock, NULL, pool);
857 }
858
859 svn_error_t *
860 svn_wc_process_committed(const char *path,
861                          svn_wc_adm_access_t *adm_access,
862                          svn_boolean_t recurse,
863                          svn_revnum_t new_revnum,
864                          const char *rev_date,
865                          const char *rev_author,
866                          const apr_array_header_t *wcprop_changes,
867                          apr_pool_t *pool)
868 {
869   return svn_wc_process_committed2(path, adm_access, recurse, new_revnum,
870                                    rev_date, rev_author, wcprop_changes,
871                                    FALSE, pool);
872 }
873
874 svn_error_t *
875 svn_wc_maybe_set_repos_root(svn_wc_adm_access_t *adm_access,
876                             const char *path,
877                             const char *repos,
878                             apr_pool_t *pool)
879 {
880   return SVN_NO_ERROR;
881 }
882
883 svn_error_t *
884 svn_wc_delete3(const char *path,
885                svn_wc_adm_access_t *adm_access,
886                svn_cancel_func_t cancel_func,
887                void *cancel_baton,
888                svn_wc_notify_func2_t notify_func,
889                void *notify_baton,
890                svn_boolean_t keep_local,
891                apr_pool_t *pool)
892 {
893   svn_wc_context_t *wc_ctx;
894   svn_wc__db_t *wc_db = svn_wc__adm_get_db(adm_access);
895   svn_wc_adm_access_t *dir_access;
896   const char *local_abspath;
897
898   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, wc_db, pool));
899   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
900
901   /* Open access batons for everything below path, because we used to open
902      these before. */
903   SVN_ERR(svn_wc_adm_probe_try3(&dir_access, adm_access, path,
904                                 TRUE, -1, cancel_func, cancel_baton, pool));
905
906   SVN_ERR(svn_wc_delete4(wc_ctx,
907                          local_abspath,
908                          keep_local,
909                          TRUE,
910                          cancel_func, cancel_baton,
911                          notify_func, notify_baton,
912                          pool));
913
914   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
915 }
916
917 svn_error_t *
918 svn_wc_delete2(const char *path,
919                svn_wc_adm_access_t *adm_access,
920                svn_cancel_func_t cancel_func,
921                void *cancel_baton,
922                svn_wc_notify_func2_t notify_func,
923                void *notify_baton,
924                apr_pool_t *pool)
925 {
926   return svn_wc_delete3(path, adm_access, cancel_func, cancel_baton,
927                         notify_func, notify_baton, FALSE, pool);
928 }
929
930 svn_error_t *
931 svn_wc_delete(const char *path,
932               svn_wc_adm_access_t *adm_access,
933               svn_cancel_func_t cancel_func,
934               void *cancel_baton,
935               svn_wc_notify_func_t notify_func,
936               void *notify_baton,
937               apr_pool_t *pool)
938 {
939   struct compat_notify_baton_t nb;
940
941   nb.func = notify_func;
942   nb.baton = notify_baton;
943
944   return svn_wc_delete2(path, adm_access, cancel_func, cancel_baton,
945                         compat_call_notify_func, &nb, pool);
946 }
947
948 svn_error_t *
949 svn_wc_add_from_disk2(svn_wc_context_t *wc_ctx,
950                      const char *local_abspath,
951                      const apr_hash_t *props,
952                      svn_wc_notify_func2_t notify_func,
953                      void *notify_baton,
954                      apr_pool_t *scratch_pool)
955 {
956   SVN_ERR(svn_wc_add_from_disk3(wc_ctx, local_abspath, props, FALSE,
957                                  notify_func, notify_baton, scratch_pool));
958   return SVN_NO_ERROR;
959 }
960
961 svn_error_t *
962 svn_wc_add_from_disk(svn_wc_context_t *wc_ctx,
963                      const char *local_abspath,
964                      svn_wc_notify_func2_t notify_func,
965                      void *notify_baton,
966                      apr_pool_t *scratch_pool)
967 {
968   SVN_ERR(svn_wc_add_from_disk2(wc_ctx, local_abspath, NULL,
969                                  notify_func, notify_baton, scratch_pool));
970   return SVN_NO_ERROR;
971 }
972
973 svn_error_t *
974 svn_wc_add3(const char *path,
975             svn_wc_adm_access_t *parent_access,
976             svn_depth_t depth,
977             const char *copyfrom_url,
978             svn_revnum_t copyfrom_rev,
979             svn_cancel_func_t cancel_func,
980             void *cancel_baton,
981             svn_wc_notify_func2_t notify_func,
982             void *notify_baton,
983             apr_pool_t *pool)
984 {
985   svn_wc_context_t *wc_ctx;
986   svn_wc__db_t *wc_db = svn_wc__adm_get_db(parent_access);
987   const char *local_abspath;
988
989   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, wc_db, pool));
990   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
991
992   SVN_ERR(svn_wc_add4(wc_ctx, local_abspath,
993                       depth, copyfrom_url,
994                       copyfrom_rev,
995                       cancel_func, cancel_baton,
996                       notify_func, notify_baton, pool));
997
998   /* Make sure the caller gets the new access baton in the set. */
999   if (svn_wc__adm_retrieve_internal2(wc_db, local_abspath, pool) == NULL)
1000     {
1001       svn_node_kind_t kind;
1002
1003       SVN_ERR(svn_wc__db_read_kind(&kind, wc_db, local_abspath,
1004                                    FALSE /* allow_missing */,
1005                                    TRUE /* show_deleted */,
1006                                    FALSE /* show_hidden */, pool));
1007       if (kind == svn_node_dir)
1008         {
1009           svn_wc_adm_access_t *adm_access;
1010
1011           /* Open the access baton in adm_access' pool to give it the same
1012              lifetime */
1013           SVN_ERR(svn_wc_adm_open3(&adm_access, parent_access, path, TRUE,
1014                                    copyfrom_url ? -1 : 0,
1015                                    cancel_func, cancel_baton,
1016                                    svn_wc_adm_access_pool(parent_access)));
1017         }
1018     }
1019
1020   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
1021 }
1022
1023
1024 svn_error_t *
1025 svn_wc_add2(const char *path,
1026             svn_wc_adm_access_t *parent_access,
1027             const char *copyfrom_url,
1028             svn_revnum_t copyfrom_rev,
1029             svn_cancel_func_t cancel_func,
1030             void *cancel_baton,
1031             svn_wc_notify_func2_t notify_func,
1032             void *notify_baton,
1033             apr_pool_t *pool)
1034 {
1035   return svn_wc_add3(path, parent_access, svn_depth_infinity,
1036                      copyfrom_url, copyfrom_rev,
1037                      cancel_func, cancel_baton,
1038                      notify_func, notify_baton, pool);
1039 }
1040
1041 svn_error_t *
1042 svn_wc_add(const char *path,
1043            svn_wc_adm_access_t *parent_access,
1044            const char *copyfrom_url,
1045            svn_revnum_t copyfrom_rev,
1046            svn_cancel_func_t cancel_func,
1047            void *cancel_baton,
1048            svn_wc_notify_func_t notify_func,
1049            void *notify_baton,
1050            apr_pool_t *pool)
1051 {
1052   struct compat_notify_baton_t nb;
1053
1054   nb.func = notify_func;
1055   nb.baton = notify_baton;
1056
1057   return svn_wc_add2(path, parent_access, copyfrom_url, copyfrom_rev,
1058                      cancel_func, cancel_baton,
1059                      compat_call_notify_func, &nb, pool);
1060 }
1061
1062 /*** From revert.c ***/
1063 svn_error_t *
1064 svn_wc_revert4(svn_wc_context_t *wc_ctx,
1065                const char *local_abspath,
1066                svn_depth_t depth,
1067                svn_boolean_t use_commit_times,
1068                const apr_array_header_t *changelist_filter,
1069                svn_cancel_func_t cancel_func,
1070                void *cancel_baton,
1071                svn_wc_notify_func2_t notify_func,
1072                void *notify_baton,
1073                apr_pool_t *scratch_pool)
1074 {
1075   return svn_error_trace(svn_wc_revert5(wc_ctx, local_abspath,
1076                                         depth,
1077                                         use_commit_times,
1078                                         changelist_filter,
1079                                         FALSE /* clear_changelists */,
1080                                         FALSE /* metadata_only */,
1081                                         cancel_func, cancel_baton,
1082                                         notify_func, notify_baton,
1083                                         scratch_pool));
1084 }
1085
1086 svn_error_t *
1087 svn_wc_revert3(const char *path,
1088                svn_wc_adm_access_t *parent_access,
1089                svn_depth_t depth,
1090                svn_boolean_t use_commit_times,
1091                const apr_array_header_t *changelist_filter,
1092                svn_cancel_func_t cancel_func,
1093                void *cancel_baton,
1094                svn_wc_notify_func2_t notify_func,
1095                void *notify_baton,
1096                apr_pool_t *pool)
1097 {
1098   svn_wc_context_t *wc_ctx;
1099   svn_wc__db_t *wc_db = svn_wc__adm_get_db(parent_access);
1100   const char *local_abspath;
1101
1102   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, wc_db, pool));
1103   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
1104
1105   SVN_ERR(svn_wc_revert4(wc_ctx,
1106                          local_abspath,
1107                          depth,
1108                          use_commit_times,
1109                          changelist_filter,
1110                          cancel_func, cancel_baton,
1111                          notify_func, notify_baton,
1112                          pool));
1113
1114   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
1115 }
1116
1117 svn_error_t *
1118 svn_wc_revert2(const char *path,
1119                svn_wc_adm_access_t *parent_access,
1120                svn_boolean_t recursive,
1121                svn_boolean_t use_commit_times,
1122                svn_cancel_func_t cancel_func,
1123                void *cancel_baton,
1124                svn_wc_notify_func2_t notify_func,
1125                void *notify_baton,
1126                apr_pool_t *pool)
1127 {
1128   return svn_wc_revert3(path, parent_access,
1129                         SVN_DEPTH_INFINITY_OR_EMPTY(recursive),
1130                         use_commit_times, NULL, cancel_func, cancel_baton,
1131                         notify_func, notify_baton, pool);
1132 }
1133
1134 svn_error_t *
1135 svn_wc_revert(const char *path,
1136               svn_wc_adm_access_t *parent_access,
1137               svn_boolean_t recursive,
1138               svn_boolean_t use_commit_times,
1139               svn_cancel_func_t cancel_func,
1140               void *cancel_baton,
1141               svn_wc_notify_func_t notify_func,
1142               void *notify_baton,
1143               apr_pool_t *pool)
1144 {
1145   struct compat_notify_baton_t nb;
1146
1147   nb.func = notify_func;
1148   nb.baton = notify_baton;
1149
1150   return svn_wc_revert2(path, parent_access, recursive, use_commit_times,
1151                         cancel_func, cancel_baton,
1152                         compat_call_notify_func, &nb, pool);
1153 }
1154
1155 svn_error_t *
1156 svn_wc_remove_from_revision_control(svn_wc_adm_access_t *adm_access,
1157                                     const char *name,
1158                                     svn_boolean_t destroy_wf,
1159                                     svn_boolean_t instant_error,
1160                                     svn_cancel_func_t cancel_func,
1161                                     void *cancel_baton,
1162                                     apr_pool_t *pool)
1163 {
1164   svn_wc_context_t *wc_ctx;
1165   svn_wc__db_t *wc_db = svn_wc__adm_get_db(adm_access);
1166   const char *local_abspath = svn_dirent_join(
1167                                     svn_wc__adm_access_abspath(adm_access),
1168                                     name,
1169                                     pool);
1170
1171   /* name must be an entry in adm_access, fail if not */
1172   SVN_ERR_ASSERT(strcmp(svn_dirent_basename(name, NULL), name) == 0);
1173   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, wc_db, pool));
1174
1175   SVN_ERR(svn_wc_remove_from_revision_control2(wc_ctx,
1176                                                local_abspath,
1177                                                destroy_wf,
1178                                                instant_error,
1179                                                cancel_func, cancel_baton,
1180                                                pool));
1181
1182   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
1183 }
1184
1185 svn_error_t *
1186 svn_wc_resolved_conflict4(const char *path,
1187                           svn_wc_adm_access_t *adm_access,
1188                           svn_boolean_t resolve_text,
1189                           svn_boolean_t resolve_props,
1190                           svn_boolean_t resolve_tree,
1191                           svn_depth_t depth,
1192                           svn_wc_conflict_choice_t conflict_choice,
1193                           svn_wc_notify_func2_t notify_func,
1194                           void *notify_baton,
1195                           svn_cancel_func_t cancel_func,
1196                           void *cancel_baton,
1197                           apr_pool_t *pool)
1198 {
1199   svn_wc_context_t *wc_ctx;
1200   svn_wc__db_t *wc_db = svn_wc__adm_get_db(adm_access);
1201   const char *local_abspath;
1202
1203   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
1204   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, wc_db, pool));
1205
1206   SVN_ERR(svn_wc_resolved_conflict5(wc_ctx,
1207                                     local_abspath,
1208                                     depth,
1209                                     resolve_text,
1210                                     resolve_props ? "" : NULL,
1211                                     resolve_tree,
1212                                     conflict_choice,
1213                                     cancel_func,
1214                                     cancel_baton,
1215                                     notify_func,
1216                                     notify_baton,
1217                                     pool));
1218
1219   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
1220
1221 }
1222
1223 svn_error_t *
1224 svn_wc_resolved_conflict(const char *path,
1225                          svn_wc_adm_access_t *adm_access,
1226                          svn_boolean_t resolve_text,
1227                          svn_boolean_t resolve_props,
1228                          svn_boolean_t recurse,
1229                          svn_wc_notify_func_t notify_func,
1230                          void *notify_baton,
1231                          apr_pool_t *pool)
1232 {
1233   struct compat_notify_baton_t nb;
1234
1235   nb.func = notify_func;
1236   nb.baton = notify_baton;
1237
1238   return svn_wc_resolved_conflict2(path, adm_access,
1239                                    resolve_text, resolve_props, recurse,
1240                                    compat_call_notify_func, &nb,
1241                                    NULL, NULL, pool);
1242
1243 }
1244
1245 svn_error_t *
1246 svn_wc_resolved_conflict2(const char *path,
1247                           svn_wc_adm_access_t *adm_access,
1248                           svn_boolean_t resolve_text,
1249                           svn_boolean_t resolve_props,
1250                           svn_boolean_t recurse,
1251                           svn_wc_notify_func2_t notify_func,
1252                           void *notify_baton,
1253                           svn_cancel_func_t cancel_func,
1254                           void *cancel_baton,
1255                           apr_pool_t *pool)
1256 {
1257   return svn_wc_resolved_conflict3(path, adm_access, resolve_text,
1258                                    resolve_props,
1259                                    SVN_DEPTH_INFINITY_OR_EMPTY(recurse),
1260                                    svn_wc_conflict_choose_merged,
1261                                    notify_func, notify_baton, cancel_func,
1262                                    cancel_baton, pool);
1263 }
1264
1265 svn_error_t *
1266 svn_wc_resolved_conflict3(const char *path,
1267                           svn_wc_adm_access_t *adm_access,
1268                           svn_boolean_t resolve_text,
1269                           svn_boolean_t resolve_props,
1270                           svn_depth_t depth,
1271                           svn_wc_conflict_choice_t conflict_choice,
1272                           svn_wc_notify_func2_t notify_func,
1273                           void *notify_baton,
1274                           svn_cancel_func_t cancel_func,
1275                           void *cancel_baton,
1276                           apr_pool_t *pool)
1277 {
1278   return svn_wc_resolved_conflict4(path, adm_access, resolve_text,
1279                                    resolve_props, FALSE, depth,
1280                                    svn_wc_conflict_choose_merged,
1281                                    notify_func, notify_baton, cancel_func,
1282                                    cancel_baton, pool);
1283 }
1284
1285 svn_error_t *
1286 svn_wc_add_lock(const char *path,
1287                 const svn_lock_t *lock,
1288                 svn_wc_adm_access_t *adm_access,
1289                 apr_pool_t *pool)
1290 {
1291   const char *local_abspath;
1292   svn_wc_context_t *wc_ctx;
1293
1294   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
1295   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
1296                                          svn_wc__adm_get_db(adm_access),
1297                                          pool));
1298
1299   SVN_ERR(svn_wc_add_lock2(wc_ctx, local_abspath, lock, pool));
1300
1301   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
1302 }
1303
1304 svn_error_t *
1305 svn_wc_remove_lock(const char *path,
1306                    svn_wc_adm_access_t *adm_access,
1307                    apr_pool_t *pool)
1308 {
1309   const char *local_abspath;
1310   svn_wc_context_t *wc_ctx;
1311
1312   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
1313   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
1314                                          svn_wc__adm_get_db(adm_access),
1315                                          pool));
1316
1317   SVN_ERR(svn_wc_remove_lock2(wc_ctx, local_abspath, pool));
1318
1319   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
1320
1321 }
1322
1323 svn_error_t *
1324 svn_wc_get_ancestry(char **url,
1325                     svn_revnum_t *rev,
1326                     const char *path,
1327                     svn_wc_adm_access_t *adm_access,
1328                     apr_pool_t *pool)
1329 {
1330   const char *local_abspath;
1331   const svn_wc_entry_t *entry;
1332
1333   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
1334
1335   SVN_ERR(svn_wc__get_entry(&entry, svn_wc__adm_get_db(adm_access),
1336                             local_abspath, FALSE,
1337                             svn_node_unknown,
1338                             pool, pool));
1339
1340   if (url)
1341     *url = apr_pstrdup(pool, entry->url);
1342
1343   if (rev)
1344     *rev = entry->revision;
1345
1346   return SVN_NO_ERROR;
1347 }
1348
1349 svn_error_t *
1350 svn_wc_set_changelist(const char *path,
1351                       const char *changelist,
1352                       svn_wc_adm_access_t *adm_access,
1353                       svn_cancel_func_t cancel_func,
1354                       void *cancel_baton,
1355                       svn_wc_notify_func2_t notify_func,
1356                       void *notify_baton,
1357                       apr_pool_t *pool)
1358 {
1359   const char *local_abspath;
1360   svn_wc_context_t *wc_ctx;
1361
1362   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
1363   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
1364                                          svn_wc__adm_get_db(adm_access),
1365                                          pool));
1366
1367   SVN_ERR(svn_wc_set_changelist2(wc_ctx, local_abspath, changelist,
1368                                  svn_depth_empty, NULL,
1369                                  cancel_func, cancel_baton, notify_func,
1370                                  notify_baton, pool));
1371
1372   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
1373 }
1374
1375
1376 /*** From diff.c ***/
1377 /* Used to wrap svn_wc_diff_callbacks_t. */
1378 struct diff_callbacks_wrapper_baton {
1379   const svn_wc_diff_callbacks_t *callbacks;
1380   void *baton;
1381 };
1382
1383 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t. */
1384 static svn_error_t *
1385 wrap_3to1_file_changed(svn_wc_adm_access_t *adm_access,
1386                        svn_wc_notify_state_t *contentstate,
1387                        svn_wc_notify_state_t *propstate,
1388                        svn_boolean_t *tree_conflicted,
1389                        const char *path,
1390                        const char *tmpfile1,
1391                        const char *tmpfile2,
1392                        svn_revnum_t rev1,
1393                        svn_revnum_t rev2,
1394                        const char *mimetype1,
1395                        const char *mimetype2,
1396                        const apr_array_header_t *propchanges,
1397                        apr_hash_t *originalprops,
1398                        void *diff_baton)
1399 {
1400   struct diff_callbacks_wrapper_baton *b = diff_baton;
1401
1402   if (tree_conflicted)
1403     *tree_conflicted = FALSE;
1404
1405   if (tmpfile2 != NULL)
1406     SVN_ERR(b->callbacks->file_changed(adm_access, contentstate, path,
1407                                        tmpfile1, tmpfile2,
1408                                        rev1, rev2, mimetype1, mimetype2,
1409                                        b->baton));
1410   if (propchanges->nelts > 0)
1411     SVN_ERR(b->callbacks->props_changed(adm_access, propstate, path,
1412                                         propchanges, originalprops,
1413                                         b->baton));
1414
1415   return SVN_NO_ERROR;
1416 }
1417
1418 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t. */
1419 static svn_error_t *
1420 wrap_3to1_file_added(svn_wc_adm_access_t *adm_access,
1421                      svn_wc_notify_state_t *contentstate,
1422                      svn_wc_notify_state_t *propstate,
1423                      svn_boolean_t *tree_conflicted,
1424                      const char *path,
1425                      const char *tmpfile1,
1426                      const char *tmpfile2,
1427                      svn_revnum_t rev1,
1428                      svn_revnum_t rev2,
1429                      const char *mimetype1,
1430                      const char *mimetype2,
1431                      const apr_array_header_t *propchanges,
1432                      apr_hash_t *originalprops,
1433                      void *diff_baton)
1434 {
1435   struct diff_callbacks_wrapper_baton *b = diff_baton;
1436
1437   if (tree_conflicted)
1438     *tree_conflicted = FALSE;
1439
1440   SVN_ERR(b->callbacks->file_added(adm_access, contentstate, path,
1441                                    tmpfile1, tmpfile2, rev1, rev2,
1442                                    mimetype1, mimetype2, b->baton));
1443   if (propchanges->nelts > 0)
1444     SVN_ERR(b->callbacks->props_changed(adm_access, propstate, path,
1445                                         propchanges, originalprops,
1446                                         b->baton));
1447
1448   return SVN_NO_ERROR;
1449 }
1450
1451 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t. */
1452 static svn_error_t *
1453 wrap_3to1_file_deleted(svn_wc_adm_access_t *adm_access,
1454                        svn_wc_notify_state_t *state,
1455                        svn_boolean_t *tree_conflicted,
1456                        const char *path,
1457                        const char *tmpfile1,
1458                        const char *tmpfile2,
1459                        const char *mimetype1,
1460                        const char *mimetype2,
1461                        apr_hash_t *originalprops,
1462                        void *diff_baton)
1463 {
1464   struct diff_callbacks_wrapper_baton *b = diff_baton;
1465
1466   if (tree_conflicted)
1467     *tree_conflicted = FALSE;
1468
1469   SVN_ERR_ASSERT(originalprops);
1470
1471   return b->callbacks->file_deleted(adm_access, state, path,
1472                                     tmpfile1, tmpfile2, mimetype1, mimetype2,
1473                                     b->baton);
1474 }
1475
1476 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t. */
1477 static svn_error_t *
1478 wrap_3to1_dir_added(svn_wc_adm_access_t *adm_access,
1479                     svn_wc_notify_state_t *state,
1480                     svn_boolean_t *tree_conflicted,
1481                     const char *path,
1482                     svn_revnum_t rev,
1483                     void *diff_baton)
1484 {
1485   struct diff_callbacks_wrapper_baton *b = diff_baton;
1486
1487   if (tree_conflicted)
1488     *tree_conflicted = FALSE;
1489
1490   return b->callbacks->dir_added(adm_access, state, path, rev, b->baton);
1491 }
1492
1493 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t. */
1494 static svn_error_t *
1495 wrap_3to1_dir_deleted(svn_wc_adm_access_t *adm_access,
1496                       svn_wc_notify_state_t *state,
1497                       svn_boolean_t *tree_conflicted,
1498                       const char *path,
1499                       void *diff_baton)
1500 {
1501   struct diff_callbacks_wrapper_baton *b = diff_baton;
1502
1503   if (tree_conflicted)
1504     *tree_conflicted = FALSE;
1505
1506   return b->callbacks->dir_deleted(adm_access, state, path, b->baton);
1507 }
1508
1509 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t. */
1510 static svn_error_t *
1511 wrap_3to1_dir_props_changed(svn_wc_adm_access_t *adm_access,
1512                             svn_wc_notify_state_t *state,
1513                             svn_boolean_t *tree_conflicted,
1514                             const char *path,
1515                             const apr_array_header_t *propchanges,
1516                             apr_hash_t *originalprops,
1517                             void *diff_baton)
1518 {
1519   struct diff_callbacks_wrapper_baton *b = diff_baton;
1520
1521   if (tree_conflicted)
1522     *tree_conflicted = FALSE;
1523
1524   return b->callbacks->props_changed(adm_access, state, path, propchanges,
1525                                      originalprops, b->baton);
1526 }
1527
1528 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t
1529    and svn_wc_diff_callbacks2_t. */
1530 static svn_error_t *
1531 wrap_3to1or2_dir_opened(svn_wc_adm_access_t *adm_access,
1532                         svn_boolean_t *tree_conflicted,
1533                         const char *path,
1534                         svn_revnum_t rev,
1535                         void *diff_baton)
1536 {
1537   if (tree_conflicted)
1538     *tree_conflicted = FALSE;
1539   /* Do nothing. */
1540   return SVN_NO_ERROR;
1541 }
1542
1543 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t
1544    and svn_wc_diff_callbacks2_t. */
1545 static svn_error_t *
1546 wrap_3to1or2_dir_closed(svn_wc_adm_access_t *adm_access,
1547                         svn_wc_notify_state_t *propstate,
1548                         svn_wc_notify_state_t *contentstate,
1549                         svn_boolean_t *tree_conflicted,
1550                         const char *path,
1551                         void *diff_baton)
1552 {
1553   if (contentstate)
1554     *contentstate = svn_wc_notify_state_unknown;
1555   if (propstate)
1556     *propstate = svn_wc_notify_state_unknown;
1557   if (tree_conflicted)
1558     *tree_conflicted = FALSE;
1559   /* Do nothing. */
1560   return SVN_NO_ERROR;
1561 }
1562
1563 /* Used to wrap svn_diff_callbacks_t as an svn_wc_diff_callbacks3_t. */
1564 static struct svn_wc_diff_callbacks3_t diff_callbacks_wrapper = {
1565   wrap_3to1_file_changed,
1566   wrap_3to1_file_added,
1567   wrap_3to1_file_deleted,
1568   wrap_3to1_dir_added,
1569   wrap_3to1_dir_deleted,
1570   wrap_3to1_dir_props_changed,
1571   wrap_3to1or2_dir_opened,
1572   wrap_3to1or2_dir_closed
1573 };
1574
1575
1576
1577 /* Used to wrap svn_wc_diff_callbacks2_t. */
1578 struct diff_callbacks2_wrapper_baton {
1579   const svn_wc_diff_callbacks2_t *callbacks2;
1580   void *baton;
1581 };
1582
1583 /* An svn_wc_diff_callbacks3_t function for wrapping
1584  * svn_wc_diff_callbacks2_t. */
1585 static svn_error_t *
1586 wrap_3to2_file_changed(svn_wc_adm_access_t *adm_access,
1587                        svn_wc_notify_state_t *contentstate,
1588                        svn_wc_notify_state_t *propstate,
1589                        svn_boolean_t *tree_conflicted,
1590                        const char *path,
1591                        const char *tmpfile1,
1592                        const char *tmpfile2,
1593                        svn_revnum_t rev1,
1594                        svn_revnum_t rev2,
1595                        const char *mimetype1,
1596                        const char *mimetype2,
1597                        const apr_array_header_t *propchanges,
1598                        apr_hash_t *originalprops,
1599                        void *diff_baton)
1600 {
1601   struct diff_callbacks2_wrapper_baton *b = diff_baton;
1602
1603   if (tree_conflicted)
1604     *tree_conflicted = FALSE;
1605
1606   return b->callbacks2->file_changed(adm_access, contentstate, propstate,
1607                                      path, tmpfile1, tmpfile2,
1608                                      rev1, rev2, mimetype1, mimetype2,
1609                                      propchanges, originalprops, b->baton);
1610 }
1611
1612 /* An svn_wc_diff_callbacks3_t function for wrapping
1613  * svn_wc_diff_callbacks2_t. */
1614 static svn_error_t *
1615 wrap_3to2_file_added(svn_wc_adm_access_t *adm_access,
1616                      svn_wc_notify_state_t *contentstate,
1617                      svn_wc_notify_state_t *propstate,
1618                      svn_boolean_t *tree_conflicted,
1619                      const char *path,
1620                      const char *tmpfile1,
1621                      const char *tmpfile2,
1622                      svn_revnum_t rev1,
1623                      svn_revnum_t rev2,
1624                      const char *mimetype1,
1625                      const char *mimetype2,
1626                      const apr_array_header_t *propchanges,
1627                      apr_hash_t *originalprops,
1628                      void *diff_baton)
1629 {
1630   struct diff_callbacks2_wrapper_baton *b = diff_baton;
1631
1632   if (tree_conflicted)
1633     *tree_conflicted = FALSE;
1634
1635   return b->callbacks2->file_added(adm_access, contentstate, propstate, path,
1636                                    tmpfile1, tmpfile2, rev1, rev2,
1637                                    mimetype1, mimetype2, propchanges,
1638                                    originalprops, b->baton);
1639 }
1640
1641 /* An svn_wc_diff_callbacks3_t function for wrapping
1642  * svn_wc_diff_callbacks2_t. */
1643 static svn_error_t *
1644 wrap_3to2_file_deleted(svn_wc_adm_access_t *adm_access,
1645                        svn_wc_notify_state_t *state,
1646                        svn_boolean_t *tree_conflicted,
1647                        const char *path,
1648                        const char *tmpfile1,
1649                        const char *tmpfile2,
1650                        const char *mimetype1,
1651                        const char *mimetype2,
1652                        apr_hash_t *originalprops,
1653                        void *diff_baton)
1654 {
1655   struct diff_callbacks2_wrapper_baton *b = diff_baton;
1656
1657   if (tree_conflicted)
1658     *tree_conflicted = FALSE;
1659
1660   return b->callbacks2->file_deleted(adm_access, state, path,
1661                                      tmpfile1, tmpfile2, mimetype1, mimetype2,
1662                                      originalprops, b->baton);
1663 }
1664
1665 /* An svn_wc_diff_callbacks3_t function for wrapping
1666  * svn_wc_diff_callbacks2_t. */
1667 static svn_error_t *
1668 wrap_3to2_dir_added(svn_wc_adm_access_t *adm_access,
1669                     svn_wc_notify_state_t *state,
1670                     svn_boolean_t *tree_conflicted,
1671                     const char *path,
1672                     svn_revnum_t rev,
1673                     void *diff_baton)
1674 {
1675   struct diff_callbacks2_wrapper_baton *b = diff_baton;
1676
1677   if (tree_conflicted)
1678     *tree_conflicted = FALSE;
1679
1680   return b->callbacks2->dir_added(adm_access, state, path, rev, b->baton);
1681 }
1682
1683 /* An svn_wc_diff_callbacks3_t function for wrapping
1684  * svn_wc_diff_callbacks2_t. */
1685 static svn_error_t *
1686 wrap_3to2_dir_deleted(svn_wc_adm_access_t *adm_access,
1687                       svn_wc_notify_state_t *state,
1688                       svn_boolean_t *tree_conflicted,
1689                       const char *path,
1690                       void *diff_baton)
1691 {
1692   struct diff_callbacks2_wrapper_baton *b = diff_baton;
1693
1694   if (tree_conflicted)
1695     *tree_conflicted = FALSE;
1696
1697   return b->callbacks2->dir_deleted(adm_access, state, path, b->baton);
1698 }
1699
1700 /* An svn_wc_diff_callbacks3_t function for wrapping
1701  * svn_wc_diff_callbacks2_t. */
1702 static svn_error_t *
1703 wrap_3to2_dir_props_changed(svn_wc_adm_access_t *adm_access,
1704                             svn_wc_notify_state_t *state,
1705                             svn_boolean_t *tree_conflicted,
1706                             const char *path,
1707                             const apr_array_header_t *propchanges,
1708                             apr_hash_t *originalprops,
1709                             void *diff_baton)
1710 {
1711   struct diff_callbacks2_wrapper_baton *b = diff_baton;
1712
1713   if (tree_conflicted)
1714     *tree_conflicted = FALSE;
1715
1716   return b->callbacks2->dir_props_changed(adm_access, state, path, propchanges,
1717                                           originalprops, b->baton);
1718 }
1719
1720 /* Used to wrap svn_diff_callbacks2_t as an svn_wc_diff_callbacks3_t. */
1721 static struct svn_wc_diff_callbacks3_t diff_callbacks2_wrapper = {
1722   wrap_3to2_file_changed,
1723   wrap_3to2_file_added,
1724   wrap_3to2_file_deleted,
1725   wrap_3to2_dir_added,
1726   wrap_3to2_dir_deleted,
1727   wrap_3to2_dir_props_changed,
1728   wrap_3to1or2_dir_opened,
1729   wrap_3to1or2_dir_closed
1730 };
1731
1732
1733
1734 /* Used to wrap svn_wc_diff_callbacks3_t. */
1735 struct diff_callbacks3_wrapper_baton {
1736   const svn_wc_diff_callbacks3_t *callbacks3;
1737   svn_wc__db_t *db;
1738   void *baton;
1739   const char *anchor;
1740   const char *anchor_abspath;
1741 };
1742
1743 static svn_error_t *
1744 wrap_4to3_file_opened(svn_boolean_t *tree_conflicted,
1745                       svn_boolean_t *skip,
1746                       const char *path,
1747                       svn_revnum_t rev,
1748                       void *diff_baton,
1749                       apr_pool_t *scratch_pool)
1750 {
1751   return SVN_NO_ERROR;
1752 }
1753
1754 /* An svn_wc_diff_callbacks4_t function for wrapping
1755  * svn_wc_diff_callbacks3_t. */
1756 static svn_error_t *
1757 wrap_4to3_file_changed(svn_wc_notify_state_t *contentstate,
1758                        svn_wc_notify_state_t *propstate,
1759                        svn_boolean_t *tree_conflicted,
1760                        const char *path,
1761                        const char *tmpfile1,
1762                        const char *tmpfile2,
1763                        svn_revnum_t rev1,
1764                        svn_revnum_t rev2,
1765                        const char *mimetype1,
1766                        const char *mimetype2,
1767                        const apr_array_header_t *propchanges,
1768                        apr_hash_t *originalprops,
1769                        void *diff_baton,
1770                        apr_pool_t *scratch_pool)
1771 {
1772   struct diff_callbacks3_wrapper_baton *b = diff_baton;
1773   svn_wc_adm_access_t *adm_access;
1774   const char *dir = svn_relpath_dirname(path, scratch_pool);
1775
1776   adm_access = svn_wc__adm_retrieve_internal2(
1777                         b->db,
1778                         svn_dirent_join(b->anchor_abspath, dir, scratch_pool),
1779                         scratch_pool);
1780
1781   return b->callbacks3->file_changed(adm_access, contentstate, propstate,
1782                                      tree_conflicted,
1783                                      svn_dirent_join(b->anchor, path,
1784                                                      scratch_pool),
1785                                      tmpfile1, tmpfile2,
1786                                      rev1, rev2, mimetype1, mimetype2,
1787                                      propchanges, originalprops, b->baton);
1788 }
1789
1790 /* An svn_wc_diff_callbacks4_t function for wrapping
1791  * svn_wc_diff_callbacks3_t. */
1792 static svn_error_t *
1793 wrap_4to3_file_added(svn_wc_notify_state_t *contentstate,
1794                      svn_wc_notify_state_t *propstate,
1795                      svn_boolean_t *tree_conflicted,
1796                      const char *path,
1797                      const char *tmpfile1,
1798                      const char *tmpfile2,
1799                      svn_revnum_t rev1,
1800                      svn_revnum_t rev2,
1801                      const char *mimetype1,
1802                      const char *mimetype2,
1803                      const char *copyfrom_path,
1804                      svn_revnum_t copyfrom_revision,
1805                      const apr_array_header_t *propchanges,
1806                      apr_hash_t *originalprops,
1807                      void *diff_baton,
1808                      apr_pool_t *scratch_pool)
1809 {
1810   struct diff_callbacks3_wrapper_baton *b = diff_baton;
1811   svn_wc_adm_access_t *adm_access;
1812   const char *dir = svn_relpath_dirname(path, scratch_pool);
1813
1814   adm_access = svn_wc__adm_retrieve_internal2(
1815                         b->db,
1816                         svn_dirent_join(b->anchor_abspath, dir, scratch_pool),
1817                         scratch_pool);
1818
1819   return b->callbacks3->file_added(adm_access, contentstate, propstate,
1820                                    tree_conflicted,
1821                                    svn_dirent_join(b->anchor, path,
1822                                                    scratch_pool),
1823                                    tmpfile1, tmpfile2,
1824                                    rev1, rev2, mimetype1, mimetype2,
1825                                    propchanges, originalprops, b->baton);
1826 }
1827
1828 /* An svn_wc_diff_callbacks4_t function for wrapping
1829  * svn_wc_diff_callbacks3_t. */
1830 static svn_error_t *
1831 wrap_4to3_file_deleted(svn_wc_notify_state_t *state,
1832                        svn_boolean_t *tree_conflicted,
1833                        const char *path,
1834                        const char *tmpfile1,
1835                        const char *tmpfile2,
1836                        const char *mimetype1,
1837                        const char *mimetype2,
1838                        apr_hash_t *originalprops,
1839                        void *diff_baton,
1840                        apr_pool_t *scratch_pool)
1841 {
1842   struct diff_callbacks3_wrapper_baton *b = diff_baton;
1843   svn_wc_adm_access_t *adm_access;
1844   const char *dir = svn_relpath_dirname(path, scratch_pool);
1845
1846   adm_access = svn_wc__adm_retrieve_internal2(
1847                         b->db,
1848                         svn_dirent_join(b->anchor_abspath, dir, scratch_pool),
1849                         scratch_pool);
1850
1851   return b->callbacks3->file_deleted(adm_access, state, tree_conflicted,
1852                                      svn_dirent_join(b->anchor, path,
1853                                                      scratch_pool),
1854                                      tmpfile1, tmpfile2,
1855                                      mimetype1, mimetype2, originalprops,
1856                                      b->baton);
1857 }
1858
1859 /* An svn_wc_diff_callbacks4_t function for wrapping
1860  * svn_wc_diff_callbacks3_t. */
1861 static svn_error_t *
1862 wrap_4to3_dir_added(svn_wc_notify_state_t *state,
1863                     svn_boolean_t *tree_conflicted,
1864                     svn_boolean_t *skip,
1865                     svn_boolean_t *skip_children,
1866                     const char *path,
1867                     svn_revnum_t rev,
1868                     const char *copyfrom_path,
1869                     svn_revnum_t copyfrom_revision,
1870                     void *diff_baton,
1871                     apr_pool_t *scratch_pool)
1872 {
1873   struct diff_callbacks3_wrapper_baton *b = diff_baton;
1874   svn_wc_adm_access_t *adm_access;
1875
1876   adm_access = svn_wc__adm_retrieve_internal2(
1877                         b->db,
1878                         svn_dirent_join(b->anchor_abspath, path, scratch_pool),
1879                         scratch_pool);
1880
1881   return b->callbacks3->dir_added(adm_access, state, tree_conflicted,
1882                                   svn_dirent_join(b->anchor, path,
1883                                                      scratch_pool),
1884                                   rev, b->baton);
1885 }
1886
1887 /* An svn_wc_diff_callbacks4_t function for wrapping
1888  * svn_wc_diff_callbacks3_t. */
1889 static svn_error_t *
1890 wrap_4to3_dir_deleted(svn_wc_notify_state_t *state,
1891                       svn_boolean_t *tree_conflicted,
1892                       const char *path,
1893                       void *diff_baton,
1894                       apr_pool_t *scratch_pool)
1895 {
1896   struct diff_callbacks3_wrapper_baton *b = diff_baton;
1897   svn_wc_adm_access_t *adm_access;
1898
1899   adm_access = svn_wc__adm_retrieve_internal2(
1900                         b->db,
1901                         svn_dirent_join(b->anchor_abspath, path, scratch_pool),
1902                         scratch_pool);
1903
1904   return b->callbacks3->dir_deleted(adm_access, state, tree_conflicted,
1905                                     svn_dirent_join(b->anchor, path,
1906                                                      scratch_pool),
1907                                     b->baton);
1908 }
1909
1910 /* An svn_wc_diff_callbacks4_t function for wrapping
1911  * svn_wc_diff_callbacks3_t. */
1912 static svn_error_t *
1913 wrap_4to3_dir_props_changed(svn_wc_notify_state_t *propstate,
1914                             svn_boolean_t *tree_conflicted,
1915                             const char *path,
1916                             svn_boolean_t dir_was_added,
1917                             const apr_array_header_t *propchanges,
1918                             apr_hash_t *original_props,
1919                             void *diff_baton,
1920                             apr_pool_t *scratch_pool)
1921 {
1922   struct diff_callbacks3_wrapper_baton *b = diff_baton;
1923   svn_wc_adm_access_t *adm_access;
1924
1925   adm_access = svn_wc__adm_retrieve_internal2(
1926                         b->db,
1927                         svn_dirent_join(b->anchor_abspath, path, scratch_pool),
1928                         scratch_pool);
1929
1930   return b->callbacks3->dir_props_changed(adm_access, propstate,
1931                                           tree_conflicted,
1932                                           svn_dirent_join(b->anchor, path,
1933                                                      scratch_pool),
1934                                           propchanges, original_props,
1935                                           b->baton);
1936 }
1937
1938 /* An svn_wc_diff_callbacks4_t function for wrapping
1939  * svn_wc_diff_callbacks3_t. */
1940 static svn_error_t *
1941 wrap_4to3_dir_opened(svn_boolean_t *tree_conflicted,
1942                      svn_boolean_t *skip,
1943                      svn_boolean_t *skip_children,
1944                      const char *path,
1945                      svn_revnum_t rev,
1946                      void *diff_baton,
1947                      apr_pool_t *scratch_pool)
1948 {
1949   struct diff_callbacks3_wrapper_baton *b = diff_baton;
1950   svn_wc_adm_access_t *adm_access;
1951
1952   adm_access = svn_wc__adm_retrieve_internal2(
1953                         b->db,
1954                         svn_dirent_join(b->anchor_abspath, path, scratch_pool),
1955                         scratch_pool);
1956   if (skip_children)
1957     *skip_children = FALSE;
1958
1959   return b->callbacks3->dir_opened(adm_access, tree_conflicted,
1960                                    svn_dirent_join(b->anchor, path,
1961                                                      scratch_pool),
1962                                    rev, b->baton);
1963 }
1964
1965 /* An svn_wc_diff_callbacks4_t function for wrapping
1966  * svn_wc_diff_callbacks3_t. */
1967 static svn_error_t *
1968 wrap_4to3_dir_closed(svn_wc_notify_state_t *contentstate,
1969                      svn_wc_notify_state_t *propstate,
1970                      svn_boolean_t *tree_conflicted,
1971                      const char *path,
1972                      svn_boolean_t dir_was_added,
1973                      void *diff_baton,
1974                      apr_pool_t *scratch_pool)
1975 {
1976   struct diff_callbacks3_wrapper_baton *b = diff_baton;
1977   svn_wc_adm_access_t *adm_access;
1978
1979   adm_access = svn_wc__adm_retrieve_internal2(
1980                         b->db,
1981                         svn_dirent_join(b->anchor_abspath, path, scratch_pool),
1982                         scratch_pool);
1983
1984   return b->callbacks3->dir_closed(adm_access, contentstate, propstate,
1985                                    tree_conflicted,
1986                                    svn_dirent_join(b->anchor, path,
1987                                                      scratch_pool),
1988                                    b->baton);
1989 }
1990
1991
1992 /* Used to wrap svn_diff_callbacks3_t as an svn_wc_diff_callbacks4_t. */
1993 static struct svn_wc_diff_callbacks4_t diff_callbacks3_wrapper = {
1994   wrap_4to3_file_opened,
1995   wrap_4to3_file_changed,
1996   wrap_4to3_file_added,
1997   wrap_4to3_file_deleted,
1998   wrap_4to3_dir_deleted,
1999   wrap_4to3_dir_opened,
2000   wrap_4to3_dir_added,
2001   wrap_4to3_dir_props_changed,
2002   wrap_4to3_dir_closed
2003 };
2004
2005
2006 svn_error_t *
2007 svn_wc_get_diff_editor6(const svn_delta_editor_t **editor,
2008                         void **edit_baton,
2009                         svn_wc_context_t *wc_ctx,
2010                         const char *anchor_abspath,
2011                         const char *target,
2012                         svn_depth_t depth,
2013                         svn_boolean_t ignore_ancestry,
2014                         svn_boolean_t show_copies_as_adds,
2015                         svn_boolean_t use_git_diff_format,
2016                         svn_boolean_t use_text_base,
2017                         svn_boolean_t reverse_order,
2018                         svn_boolean_t server_performs_filtering,
2019                         const apr_array_header_t *changelist_filter,
2020                         const svn_wc_diff_callbacks4_t *callbacks,
2021                         void *callback_baton,
2022                         svn_cancel_func_t cancel_func,
2023                         void *cancel_baton,
2024                         apr_pool_t *result_pool,
2025                         apr_pool_t *scratch_pool)
2026 {
2027   const svn_diff_tree_processor_t *diff_processor;
2028
2029   /* --git implies --show-copies-as-adds */
2030   if (use_git_diff_format)
2031     show_copies_as_adds = TRUE;
2032
2033   /* --show-copies-as-adds implies --notice-ancestry */
2034   if (show_copies_as_adds)
2035     ignore_ancestry = FALSE;
2036
2037   SVN_ERR(svn_wc__wrap_diff_callbacks(&diff_processor,
2038                                       callbacks, callback_baton, TRUE,
2039                                       result_pool, scratch_pool));
2040
2041   if (reverse_order)
2042     diff_processor = svn_diff__tree_processor_reverse_create(
2043                               diff_processor, NULL, result_pool);
2044
2045   if (! show_copies_as_adds)
2046     diff_processor = svn_diff__tree_processor_copy_as_changed_create(
2047                               diff_processor, result_pool);
2048
2049   return svn_error_trace(
2050     svn_wc__get_diff_editor(editor, edit_baton,
2051                             wc_ctx,
2052                             anchor_abspath, target,
2053                             depth,
2054                             ignore_ancestry, use_text_base,
2055                             reverse_order, server_performs_filtering,
2056                             changelist_filter,
2057                             diff_processor,
2058                             cancel_func, cancel_baton,
2059                             result_pool, scratch_pool));
2060 }
2061
2062
2063 svn_error_t *
2064 svn_wc_get_diff_editor5(svn_wc_adm_access_t *anchor,
2065                         const char *target,
2066                         const svn_wc_diff_callbacks3_t *callbacks,
2067                         void *callback_baton,
2068                         svn_depth_t depth,
2069                         svn_boolean_t ignore_ancestry,
2070                         svn_boolean_t use_text_base,
2071                         svn_boolean_t reverse_order,
2072                         svn_cancel_func_t cancel_func,
2073                         void *cancel_baton,
2074                         const apr_array_header_t *changelist_filter,
2075                         const svn_delta_editor_t **editor,
2076                         void **edit_baton,
2077                         apr_pool_t *pool)
2078 {
2079   struct diff_callbacks3_wrapper_baton *b = apr_palloc(pool, sizeof(*b));
2080   svn_wc_context_t *wc_ctx;
2081   svn_wc__db_t *db = svn_wc__adm_get_db(anchor);
2082
2083   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, db, pool));
2084
2085   b->callbacks3 = callbacks;
2086   b->baton = callback_baton;
2087   b->db = db;
2088   b->anchor = svn_wc_adm_access_path(anchor);
2089   b->anchor_abspath = svn_wc__adm_access_abspath(anchor);
2090
2091   SVN_ERR(svn_wc_get_diff_editor6(editor,
2092                                    edit_baton,
2093                                    wc_ctx,
2094                                    b->anchor_abspath,
2095                                    target,
2096                                    depth,
2097                                    ignore_ancestry,
2098                                    FALSE,
2099                                    FALSE,
2100                                    use_text_base,
2101                                    reverse_order,
2102                                    FALSE,
2103                                    changelist_filter,
2104                                    &diff_callbacks3_wrapper,
2105                                    b,
2106                                    cancel_func,
2107                                    cancel_baton,
2108                                    pool,
2109                                    pool));
2110
2111   /* Can't destroy wc_ctx. It is used by the diff editor */
2112
2113    return SVN_NO_ERROR;
2114 }
2115
2116 svn_error_t *
2117 svn_wc_get_diff_editor4(svn_wc_adm_access_t *anchor,
2118                         const char *target,
2119                         const svn_wc_diff_callbacks2_t *callbacks,
2120                         void *callback_baton,
2121                         svn_depth_t depth,
2122                         svn_boolean_t ignore_ancestry,
2123                         svn_boolean_t use_text_base,
2124                         svn_boolean_t reverse_order,
2125                         svn_cancel_func_t cancel_func,
2126                         void *cancel_baton,
2127                         const apr_array_header_t *changelist_filter,
2128                         const svn_delta_editor_t **editor,
2129                         void **edit_baton,
2130                         apr_pool_t *pool)
2131 {
2132   struct diff_callbacks2_wrapper_baton *b = apr_palloc(pool, sizeof(*b));
2133   b->callbacks2 = callbacks;
2134   b->baton = callback_baton;
2135   return svn_wc_get_diff_editor5(anchor,
2136                                  target,
2137                                  &diff_callbacks2_wrapper,
2138                                  b,
2139                                  depth,
2140                                  ignore_ancestry,
2141                                  use_text_base,
2142                                  reverse_order,
2143                                  cancel_func,
2144                                  cancel_baton,
2145                                  changelist_filter,
2146                                  editor,
2147                                  edit_baton,
2148                                  pool);
2149 }
2150
2151 svn_error_t *
2152 svn_wc_get_diff_editor3(svn_wc_adm_access_t *anchor,
2153                         const char *target,
2154                         const svn_wc_diff_callbacks2_t *callbacks,
2155                         void *callback_baton,
2156                         svn_boolean_t recurse,
2157                         svn_boolean_t ignore_ancestry,
2158                         svn_boolean_t use_text_base,
2159                         svn_boolean_t reverse_order,
2160                         svn_cancel_func_t cancel_func,
2161                         void *cancel_baton,
2162                         const svn_delta_editor_t **editor,
2163                         void **edit_baton,
2164                         apr_pool_t *pool)
2165 {
2166   return svn_wc_get_diff_editor4(anchor,
2167                                  target,
2168                                  callbacks,
2169                                  callback_baton,
2170                                  SVN_DEPTH_INFINITY_OR_FILES(recurse),
2171                                  ignore_ancestry,
2172                                  use_text_base,
2173                                  reverse_order,
2174                                  cancel_func,
2175                                  cancel_baton,
2176                                  NULL,
2177                                  editor,
2178                                  edit_baton,
2179                                  pool);
2180 }
2181
2182 svn_error_t *
2183 svn_wc_get_diff_editor2(svn_wc_adm_access_t *anchor,
2184                         const char *target,
2185                         const svn_wc_diff_callbacks_t *callbacks,
2186                         void *callback_baton,
2187                         svn_boolean_t recurse,
2188                         svn_boolean_t ignore_ancestry,
2189                         svn_boolean_t use_text_base,
2190                         svn_boolean_t reverse_order,
2191                         svn_cancel_func_t cancel_func,
2192                         void *cancel_baton,
2193                         const svn_delta_editor_t **editor,
2194                         void **edit_baton,
2195                         apr_pool_t *pool)
2196 {
2197   struct diff_callbacks_wrapper_baton *b = apr_palloc(pool, sizeof(*b));
2198   b->callbacks = callbacks;
2199   b->baton = callback_baton;
2200   return svn_wc_get_diff_editor5(anchor, target, &diff_callbacks_wrapper, b,
2201                                  SVN_DEPTH_INFINITY_OR_FILES(recurse),
2202                                  ignore_ancestry, use_text_base,
2203                                  reverse_order, cancel_func, cancel_baton,
2204                                  NULL, editor, edit_baton, pool);
2205 }
2206
2207 svn_error_t *
2208 svn_wc_get_diff_editor(svn_wc_adm_access_t *anchor,
2209                        const char *target,
2210                        const svn_wc_diff_callbacks_t *callbacks,
2211                        void *callback_baton,
2212                        svn_boolean_t recurse,
2213                        svn_boolean_t use_text_base,
2214                        svn_boolean_t reverse_order,
2215                        svn_cancel_func_t cancel_func,
2216                        void *cancel_baton,
2217                        const svn_delta_editor_t **editor,
2218                        void **edit_baton,
2219                        apr_pool_t *pool)
2220 {
2221   return svn_wc_get_diff_editor2(anchor, target, callbacks, callback_baton,
2222                                  recurse, FALSE, use_text_base, reverse_order,
2223                                  cancel_func, cancel_baton,
2224                                  editor, edit_baton, pool);
2225 }
2226
2227 svn_error_t *
2228 svn_wc_diff5(svn_wc_adm_access_t *anchor,
2229              const char *target,
2230              const svn_wc_diff_callbacks3_t *callbacks,
2231              void *callback_baton,
2232              svn_depth_t depth,
2233              svn_boolean_t ignore_ancestry,
2234              const apr_array_header_t *changelist_filter,
2235              apr_pool_t *pool)
2236 {
2237   struct diff_callbacks3_wrapper_baton *b = apr_palloc(pool, sizeof(*b));
2238   svn_wc_context_t *wc_ctx;
2239   svn_wc__db_t *db = svn_wc__adm_get_db(anchor);
2240
2241   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, db, pool));
2242
2243   b->callbacks3 = callbacks;
2244   b->baton = callback_baton;
2245   b->anchor = svn_wc_adm_access_path(anchor);
2246   b->anchor_abspath = svn_wc__adm_access_abspath(anchor);
2247
2248   SVN_ERR(svn_wc_diff6(wc_ctx,
2249                        svn_dirent_join(b->anchor_abspath, target, pool),
2250                        &diff_callbacks3_wrapper,
2251                        b,
2252                        depth,
2253                        ignore_ancestry,
2254                        FALSE,
2255                        FALSE,
2256                        changelist_filter,
2257                        NULL, NULL,
2258                        pool));
2259
2260   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
2261 }
2262
2263 svn_error_t *
2264 svn_wc_diff4(svn_wc_adm_access_t *anchor,
2265              const char *target,
2266              const svn_wc_diff_callbacks2_t *callbacks,
2267              void *callback_baton,
2268              svn_depth_t depth,
2269              svn_boolean_t ignore_ancestry,
2270              const apr_array_header_t *changelist_filter,
2271              apr_pool_t *pool)
2272 {
2273   struct diff_callbacks2_wrapper_baton *b = apr_palloc(pool, sizeof(*b));
2274   b->callbacks2 = callbacks;
2275   b->baton = callback_baton;
2276
2277   return svn_wc_diff5(anchor, target, &diff_callbacks2_wrapper, b,
2278                       depth, ignore_ancestry, changelist_filter, pool);
2279 }
2280
2281 svn_error_t *
2282 svn_wc_diff3(svn_wc_adm_access_t *anchor,
2283              const char *target,
2284              const svn_wc_diff_callbacks2_t *callbacks,
2285              void *callback_baton,
2286              svn_boolean_t recurse,
2287              svn_boolean_t ignore_ancestry,
2288              apr_pool_t *pool)
2289 {
2290   return svn_wc_diff4(anchor, target, callbacks, callback_baton,
2291                       SVN_DEPTH_INFINITY_OR_FILES(recurse), ignore_ancestry,
2292                       NULL, pool);
2293 }
2294
2295 svn_error_t *
2296 svn_wc_diff2(svn_wc_adm_access_t *anchor,
2297              const char *target,
2298              const svn_wc_diff_callbacks_t *callbacks,
2299              void *callback_baton,
2300              svn_boolean_t recurse,
2301              svn_boolean_t ignore_ancestry,
2302              apr_pool_t *pool)
2303 {
2304   struct diff_callbacks_wrapper_baton *b = apr_pcalloc(pool, sizeof(*b));
2305   b->callbacks = callbacks;
2306   b->baton = callback_baton;
2307   return svn_wc_diff5(anchor, target, &diff_callbacks_wrapper, b,
2308                       SVN_DEPTH_INFINITY_OR_FILES(recurse), ignore_ancestry,
2309                       NULL, pool);
2310 }
2311
2312 svn_error_t *
2313 svn_wc_diff(svn_wc_adm_access_t *anchor,
2314             const char *target,
2315             const svn_wc_diff_callbacks_t *callbacks,
2316             void *callback_baton,
2317             svn_boolean_t recurse,
2318             apr_pool_t *pool)
2319 {
2320   return svn_wc_diff2(anchor, target, callbacks, callback_baton,
2321                       recurse, FALSE, pool);
2322 }
2323
2324 /*** From entries.c ***/
2325 svn_error_t *
2326 svn_wc_walk_entries2(const char *path,
2327                      svn_wc_adm_access_t *adm_access,
2328                      const svn_wc_entry_callbacks_t *walk_callbacks,
2329                      void *walk_baton,
2330                      svn_boolean_t show_hidden,
2331                      svn_cancel_func_t cancel_func,
2332                      void *cancel_baton,
2333                      apr_pool_t *pool)
2334 {
2335   svn_wc_entry_callbacks2_t walk_cb2 = { 0 };
2336   walk_cb2.found_entry = walk_callbacks->found_entry;
2337   walk_cb2.handle_error = svn_wc__walker_default_error_handler;
2338   return svn_wc_walk_entries3(path, adm_access,
2339                               &walk_cb2, walk_baton, svn_depth_infinity,
2340                               show_hidden, cancel_func, cancel_baton, pool);
2341 }
2342
2343 svn_error_t *
2344 svn_wc_walk_entries(const char *path,
2345                     svn_wc_adm_access_t *adm_access,
2346                     const svn_wc_entry_callbacks_t *walk_callbacks,
2347                     void *walk_baton,
2348                     svn_boolean_t show_hidden,
2349                     apr_pool_t *pool)
2350 {
2351   return svn_wc_walk_entries2(path, adm_access, walk_callbacks,
2352                               walk_baton, show_hidden, NULL, NULL,
2353                               pool);
2354 }
2355
2356 svn_error_t *
2357 svn_wc_mark_missing_deleted(const char *path,
2358                             svn_wc_adm_access_t *parent,
2359                             apr_pool_t *pool)
2360 {
2361   /* With a single DB a node will never be missing */
2362   return svn_error_createf(SVN_ERR_WC_PATH_FOUND, NULL,
2363                            _("Unexpectedly found '%s': "
2364                              "path is marked 'missing'"),
2365                            svn_dirent_local_style(path, pool));
2366 }
2367
2368
2369 /*** From props.c ***/
2370 svn_error_t *
2371 svn_wc_parse_externals_description2(apr_array_header_t **externals_p,
2372                                     const char *parent_directory,
2373                                     const char *desc,
2374                                     apr_pool_t *pool)
2375 {
2376   apr_array_header_t *list;
2377   apr_pool_t *subpool = svn_pool_create(pool);
2378
2379   SVN_ERR(svn_wc_parse_externals_description3(externals_p ? &list : NULL,
2380                                               parent_directory, desc,
2381                                               TRUE, subpool));
2382
2383   if (externals_p)
2384     {
2385       int i;
2386
2387       *externals_p = apr_array_make(pool, list->nelts,
2388                                     sizeof(svn_wc_external_item_t *));
2389       for (i = 0; i < list->nelts; i++)
2390         {
2391           svn_wc_external_item2_t *item2 = APR_ARRAY_IDX(list, i,
2392                                              svn_wc_external_item2_t *);
2393           svn_wc_external_item_t *item = apr_palloc(pool, sizeof (*item));
2394
2395           if (item2->target_dir)
2396             item->target_dir = apr_pstrdup(pool, item2->target_dir);
2397           if (item2->url)
2398             item->url = apr_pstrdup(pool, item2->url);
2399           item->revision = item2->revision;
2400
2401           APR_ARRAY_PUSH(*externals_p, svn_wc_external_item_t *) = item;
2402         }
2403     }
2404
2405   svn_pool_destroy(subpool);
2406
2407   return SVN_NO_ERROR;
2408 }
2409
2410
2411 svn_error_t *
2412 svn_wc_parse_externals_description(apr_hash_t **externals_p,
2413                                    const char *parent_directory,
2414                                    const char *desc,
2415                                    apr_pool_t *pool)
2416 {
2417   apr_array_header_t *list;
2418
2419   SVN_ERR(svn_wc_parse_externals_description2(externals_p ? &list : NULL,
2420                                               parent_directory, desc, pool));
2421
2422   /* Store all of the items into the hash if that was requested. */
2423   if (externals_p)
2424     {
2425       int i;
2426
2427       *externals_p = apr_hash_make(pool);
2428       for (i = 0; i < list->nelts; i++)
2429         {
2430           svn_wc_external_item_t *item;
2431           item = APR_ARRAY_IDX(list, i, svn_wc_external_item_t *);
2432
2433           svn_hash_sets(*externals_p, item->target_dir, item);
2434         }
2435     }
2436   return SVN_NO_ERROR;
2437 }
2438
2439 svn_error_t *
2440 svn_wc_prop_set3(const char *name,
2441                  const svn_string_t *value,
2442                  const char *path,
2443                  svn_wc_adm_access_t *adm_access,
2444                  svn_boolean_t skip_checks,
2445                  svn_wc_notify_func2_t notify_func,
2446                  void *notify_baton,
2447                  apr_pool_t *pool)
2448 {
2449   svn_wc_context_t *wc_ctx;
2450   const char *local_abspath;
2451   svn_error_t *err;
2452
2453   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
2454   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
2455                                          svn_wc__adm_get_db(adm_access),
2456                                          pool));
2457
2458   err = svn_wc_prop_set4(wc_ctx, local_abspath,
2459                          name, value,
2460                          svn_depth_empty,
2461                          skip_checks, NULL /* changelist_filter */,
2462                          NULL, NULL /* cancellation */,
2463                          notify_func, notify_baton,
2464                          pool);
2465
2466   if (err && err->apr_err == SVN_ERR_WC_INVALID_SCHEDULE)
2467     svn_error_clear(err);
2468   else
2469     SVN_ERR(err);
2470
2471   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
2472 }
2473
2474 svn_error_t *
2475 svn_wc_prop_set2(const char *name,
2476                  const svn_string_t *value,
2477                  const char *path,
2478                  svn_wc_adm_access_t *adm_access,
2479                  svn_boolean_t skip_checks,
2480                  apr_pool_t *pool)
2481 {
2482   return svn_wc_prop_set3(name, value, path, adm_access, skip_checks,
2483                           NULL, NULL, pool);
2484 }
2485
2486 svn_error_t *
2487 svn_wc_prop_set(const char *name,
2488                 const svn_string_t *value,
2489                 const char *path,
2490                 svn_wc_adm_access_t *adm_access,
2491                 apr_pool_t *pool)
2492 {
2493   return svn_wc_prop_set2(name, value, path, adm_access, FALSE, pool);
2494 }
2495
2496 svn_error_t *
2497 svn_wc_prop_list(apr_hash_t **props,
2498                  const char *path,
2499                  svn_wc_adm_access_t *adm_access,
2500                  apr_pool_t *pool)
2501 {
2502   svn_wc_context_t *wc_ctx;
2503   const char *local_abspath;
2504   svn_error_t *err;
2505
2506   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
2507   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
2508                                          svn_wc__adm_get_db(adm_access), pool));
2509
2510   err = svn_wc_prop_list2(props, wc_ctx, local_abspath, pool, pool);
2511   if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
2512     {
2513       *props = apr_hash_make(pool);
2514       svn_error_clear(err);
2515       err = NULL;
2516     }
2517
2518   return svn_error_compose_create(err, svn_wc_context_destroy(wc_ctx));
2519 }
2520
2521 svn_error_t *
2522 svn_wc_prop_get(const svn_string_t **value,
2523                 const char *name,
2524                 const char *path,
2525                 svn_wc_adm_access_t *adm_access,
2526                 apr_pool_t *pool)
2527 {
2528
2529   svn_wc_context_t *wc_ctx;
2530   const char *local_abspath;
2531   svn_error_t *err;
2532
2533   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
2534   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
2535                                          svn_wc__adm_get_db(adm_access), pool));
2536
2537   err = svn_wc_prop_get2(value, wc_ctx, local_abspath, name, pool, pool);
2538
2539   if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
2540     {
2541       *value = NULL;
2542       svn_error_clear(err);
2543       err = NULL;
2544     }
2545
2546   return svn_error_compose_create(err, svn_wc_context_destroy(wc_ctx));
2547 }
2548
2549 /* baton for conflict_func_1to2_wrapper */
2550 struct conflict_func_1to2_baton
2551 {
2552   svn_wc_conflict_resolver_func_t inner_func;
2553   void *inner_baton;
2554 };
2555
2556
2557 /* Implements svn_wc_conflict_resolver_func2_t */
2558 static svn_error_t *
2559 conflict_func_1to2_wrapper(svn_wc_conflict_result_t **result,
2560                            const svn_wc_conflict_description2_t *conflict,
2561                            void *baton,
2562                            apr_pool_t *result_pool,
2563                            apr_pool_t *scratch_pool)
2564 {
2565   struct conflict_func_1to2_baton *btn = baton;
2566   svn_wc_conflict_description_t *cd = svn_wc__cd2_to_cd(conflict,
2567                                                         scratch_pool);
2568
2569   return svn_error_trace(btn->inner_func(result, cd, btn->inner_baton,
2570                                          result_pool));
2571 }
2572
2573 svn_error_t *
2574 svn_wc_merge_props2(svn_wc_notify_state_t *state,
2575                     const char *path,
2576                     svn_wc_adm_access_t *adm_access,
2577                     apr_hash_t *baseprops,
2578                     const apr_array_header_t *propchanges,
2579                     svn_boolean_t base_merge,
2580                     svn_boolean_t dry_run,
2581                     svn_wc_conflict_resolver_func_t conflict_func,
2582                     void *conflict_baton,
2583                     apr_pool_t *scratch_pool)
2584 {
2585   const char *local_abspath;
2586   svn_error_t *err;
2587   svn_wc_context_t *wc_ctx;
2588   struct conflict_func_1to2_baton conflict_wrapper;
2589
2590   if (base_merge && !dry_run)
2591     return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
2592                             U_("base_merge=TRUE is no longer supported; "
2593                                "see notes/api-errata/1.7/wc006.txt"));
2594
2595   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
2596
2597   conflict_wrapper.inner_func = conflict_func;
2598   conflict_wrapper.inner_baton = conflict_baton;
2599
2600   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL,
2601                                          svn_wc__adm_get_db(adm_access),
2602                                          scratch_pool));
2603
2604   err = svn_wc_merge_props3(state,
2605                             wc_ctx,
2606                             local_abspath,
2607                             NULL /* left_version */,
2608                             NULL /* right_version */,
2609                             baseprops,
2610                             propchanges,
2611                             dry_run,
2612                             conflict_func ? conflict_func_1to2_wrapper
2613                                           : NULL,
2614                             &conflict_wrapper,
2615                             NULL, NULL,
2616                             scratch_pool);
2617
2618   if (err)
2619     switch(err->apr_err)
2620       {
2621         case SVN_ERR_WC_PATH_NOT_FOUND:
2622         case SVN_ERR_WC_PATH_UNEXPECTED_STATUS:
2623           err->apr_err = SVN_ERR_UNVERSIONED_RESOURCE;
2624           break;
2625       }
2626   return svn_error_trace(
2627             svn_error_compose_create(err,
2628                                      svn_wc_context_destroy(wc_ctx)));
2629 }
2630
2631 svn_error_t *
2632 svn_wc_merge_props(svn_wc_notify_state_t *state,
2633                    const char *path,
2634                    svn_wc_adm_access_t *adm_access,
2635                    apr_hash_t *baseprops,
2636                    const apr_array_header_t *propchanges,
2637                    svn_boolean_t base_merge,
2638                    svn_boolean_t dry_run,
2639                    apr_pool_t *pool)
2640 {
2641   return svn_wc_merge_props2(state, path, adm_access, baseprops, propchanges,
2642                              base_merge, dry_run, NULL, NULL, pool);
2643 }
2644
2645
2646 svn_error_t *
2647 svn_wc_merge_prop_diffs(svn_wc_notify_state_t *state,
2648                         const char *path,
2649                         svn_wc_adm_access_t *adm_access,
2650                         const apr_array_header_t *propchanges,
2651                         svn_boolean_t base_merge,
2652                         svn_boolean_t dry_run,
2653                         apr_pool_t *pool)
2654 {
2655   /* NOTE: Here, we use implementation knowledge.  The public
2656      svn_wc_merge_props2 doesn't allow NULL as baseprops argument, but we know
2657      that it works. */
2658   return svn_wc_merge_props2(state, path, adm_access, NULL, propchanges,
2659                              base_merge, dry_run, NULL, NULL, pool);
2660 }
2661
2662 svn_error_t *
2663 svn_wc_get_prop_diffs(apr_array_header_t **propchanges,
2664                       apr_hash_t **original_props,
2665                       const char *path,
2666                       svn_wc_adm_access_t *adm_access,
2667                       apr_pool_t *pool)
2668 {
2669   svn_wc_context_t *wc_ctx;
2670   const char *local_abspath;
2671
2672   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
2673   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
2674                                          svn_wc__adm_get_db(adm_access), pool));
2675
2676   SVN_ERR(svn_wc_get_prop_diffs2(propchanges, original_props, wc_ctx,
2677                                  local_abspath, pool, pool));
2678
2679   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
2680 }
2681
2682
2683 svn_error_t *
2684 svn_wc_props_modified_p(svn_boolean_t *modified_p,
2685                         const char *path,
2686                         svn_wc_adm_access_t *adm_access,
2687                         apr_pool_t *pool)
2688 {
2689   svn_wc_context_t *wc_ctx;
2690   const char *local_abspath;
2691   svn_error_t *err;
2692
2693   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
2694   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
2695                                          svn_wc__adm_get_db(adm_access), pool));
2696
2697   err = svn_wc_props_modified_p2(modified_p,
2698                                  wc_ctx,
2699                                  local_abspath,
2700                                  pool);
2701
2702   if (err)
2703     {
2704       if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
2705         return svn_error_trace(err);
2706
2707       svn_error_clear(err);
2708       *modified_p = FALSE;
2709     }
2710
2711   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
2712 }
2713
2714
2715 svn_error_t *
2716 svn_wc__status2_from_3(svn_wc_status2_t **status,
2717                        const svn_wc_status3_t *old_status,
2718                        svn_wc_context_t *wc_ctx,
2719                        const char *local_abspath,
2720                        apr_pool_t *result_pool,
2721                        apr_pool_t *scratch_pool)
2722 {
2723   const svn_wc_entry_t *entry = NULL;
2724
2725   if (old_status == NULL)
2726     {
2727       *status = NULL;
2728       return SVN_NO_ERROR;
2729     }
2730
2731   *status = apr_pcalloc(result_pool, sizeof(**status));
2732
2733   if (old_status->versioned)
2734     {
2735       svn_error_t *err;
2736       err= svn_wc__get_entry(&entry, wc_ctx->db, local_abspath, FALSE,
2737                              svn_node_unknown, result_pool, scratch_pool);
2738
2739       if (err && err->apr_err == SVN_ERR_NODE_UNEXPECTED_KIND)
2740         svn_error_clear(err);
2741       else
2742         SVN_ERR(err);
2743     }
2744
2745   (*status)->entry = entry;
2746   (*status)->copied = old_status->copied;
2747   (*status)->repos_lock = svn_lock_dup(old_status->repos_lock, result_pool);
2748
2749   if (old_status->repos_relpath)
2750     (*status)->url = svn_path_url_add_component2(old_status->repos_root_url,
2751                                                  old_status->repos_relpath,
2752                                                  result_pool);
2753   (*status)->ood_last_cmt_rev = old_status->ood_changed_rev;
2754   (*status)->ood_last_cmt_date = old_status->ood_changed_date;
2755   (*status)->ood_kind = old_status->ood_kind;
2756   (*status)->ood_last_cmt_author = old_status->ood_changed_author;
2757
2758   if (old_status->conflicted)
2759     {
2760       const svn_wc_conflict_description2_t *tree_conflict2;
2761       SVN_ERR(svn_wc__get_tree_conflict(&tree_conflict2, wc_ctx, local_abspath,
2762                                         scratch_pool, scratch_pool));
2763       (*status)->tree_conflict = svn_wc__cd2_to_cd(tree_conflict2, result_pool);
2764     }
2765
2766   (*status)->switched = old_status->switched;
2767
2768   (*status)->text_status = old_status->node_status;
2769   (*status)->prop_status = old_status->prop_status;
2770
2771   (*status)->repos_text_status = old_status->repos_node_status;
2772   (*status)->repos_prop_status = old_status->repos_prop_status;
2773
2774   /* Some values might be inherited from properties */
2775   if (old_status->node_status == svn_wc_status_modified
2776       || old_status->node_status == svn_wc_status_conflicted)
2777     (*status)->text_status = old_status->text_status;
2778
2779   /* (Currently a no-op, but just make sure it is ok) */
2780   if (old_status->repos_node_status == svn_wc_status_modified
2781       || old_status->repos_node_status == svn_wc_status_conflicted)
2782     (*status)->repos_text_status = old_status->repos_text_status;
2783
2784   if (old_status->node_status == svn_wc_status_added)
2785     (*status)->prop_status = svn_wc_status_none; /* No separate info */
2786
2787   /* Find pristine_text_status value */
2788   switch (old_status->text_status)
2789     {
2790       case svn_wc_status_none:
2791       case svn_wc_status_normal:
2792       case svn_wc_status_modified:
2793         (*status)->pristine_text_status = old_status->text_status;
2794         break;
2795       case svn_wc_status_conflicted:
2796       default:
2797         /* ### Fetch compare data, or fall back to the documented
2798                not retrieved behavior? */
2799         (*status)->pristine_text_status = svn_wc_status_none;
2800         break;
2801     }
2802
2803   /* Find pristine_prop_status value */
2804   switch (old_status->prop_status)
2805     {
2806       case svn_wc_status_none:
2807       case svn_wc_status_normal:
2808       case svn_wc_status_modified:
2809         if (old_status->node_status != svn_wc_status_added
2810             && old_status->node_status != svn_wc_status_deleted
2811             && old_status->node_status != svn_wc_status_replaced)
2812           {
2813             (*status)->pristine_prop_status = old_status->prop_status;
2814           }
2815         else
2816           (*status)->pristine_prop_status = svn_wc_status_none;
2817         break;
2818       case svn_wc_status_conflicted:
2819       default:
2820         /* ### Fetch compare data, or fall back to the documented
2821                not retrieved behavior? */
2822         (*status)->pristine_prop_status = svn_wc_status_none;
2823         break;
2824     }
2825
2826   if (old_status->versioned
2827       && old_status->conflicted
2828       && old_status->node_status != svn_wc_status_obstructed
2829       && (old_status->kind == svn_node_file
2830           || old_status->node_status != svn_wc_status_missing))
2831     {
2832       svn_boolean_t text_conflict_p, prop_conflict_p;
2833
2834       /* The entry says there was a conflict, but the user might have
2835          marked it as resolved by deleting the artifact files, so check
2836          for that. */
2837       SVN_ERR(svn_wc__internal_conflicted_p(&text_conflict_p,
2838                                             &prop_conflict_p,
2839                                             NULL,
2840                                             wc_ctx->db, local_abspath,
2841                                             scratch_pool));
2842
2843       if (text_conflict_p)
2844         (*status)->text_status = svn_wc_status_conflicted;
2845
2846       if (prop_conflict_p)
2847         (*status)->prop_status = svn_wc_status_conflicted;
2848     }
2849
2850   return SVN_NO_ERROR;
2851 }
2852
2853
2854
2855 /*** From status.c ***/
2856
2857 struct status4_wrapper_baton
2858 {
2859   svn_wc_status_func3_t old_func;
2860   void *old_baton;
2861   const char *anchor_abspath;
2862   const char *anchor_relpath;
2863   svn_wc_context_t *wc_ctx;
2864 };
2865
2866 /* */
2867 static svn_error_t *
2868 status4_wrapper_func(void *baton,
2869                      const char *local_abspath,
2870                      const svn_wc_status3_t *status,
2871                      apr_pool_t *scratch_pool)
2872 {
2873   struct status4_wrapper_baton *swb = baton;
2874   svn_wc_status2_t *dup;
2875   const char *path = local_abspath;
2876
2877   SVN_ERR(svn_wc__status2_from_3(&dup, status, swb->wc_ctx, local_abspath,
2878                                  scratch_pool, scratch_pool));
2879
2880   if (swb->anchor_abspath != NULL)
2881     {
2882       path = svn_dirent_join(
2883                 swb->anchor_relpath,
2884                 svn_dirent_skip_ancestor(swb->anchor_abspath, local_abspath),
2885                 scratch_pool);
2886     }
2887
2888   return (*swb->old_func)(swb->old_baton, path, dup, scratch_pool);
2889 }
2890
2891
2892 svn_error_t *
2893 svn_wc_get_status_editor5(const svn_delta_editor_t **editor,
2894                           void **edit_baton,
2895                           void **set_locks_baton,
2896                           svn_revnum_t *edit_revision,
2897                           svn_wc_context_t *wc_ctx,
2898                           const char *anchor_abspath,
2899                           const char *target_basename,
2900                           svn_depth_t depth,
2901                           svn_boolean_t get_all,
2902                           svn_boolean_t no_ignore,
2903                           svn_boolean_t depth_as_sticky,
2904                           svn_boolean_t server_performs_filtering,
2905                           const apr_array_header_t *ignore_patterns,
2906                           svn_wc_status_func4_t status_func,
2907                           void *status_baton,
2908                           svn_cancel_func_t cancel_func,
2909                           void *cancel_baton,
2910                           apr_pool_t *result_pool,
2911                           apr_pool_t *scratch_pool)
2912 {
2913   return svn_error_trace(
2914     svn_wc__get_status_editor(editor, edit_baton,
2915                               set_locks_baton,
2916                               edit_revision,
2917                               wc_ctx,
2918                               anchor_abspath,
2919                               target_basename,
2920                               depth, get_all,
2921                               TRUE, /* check_working_copy */
2922                               no_ignore, depth_as_sticky,
2923                               server_performs_filtering,
2924                               ignore_patterns,
2925                               status_func, status_baton,
2926                               cancel_func, cancel_baton,
2927                               result_pool,
2928                               scratch_pool));
2929 }
2930
2931
2932 svn_error_t *
2933 svn_wc_get_status_editor4(const svn_delta_editor_t **editor,
2934                           void **edit_baton,
2935                           void **set_locks_baton,
2936                           svn_revnum_t *edit_revision,
2937                           svn_wc_adm_access_t *anchor,
2938                           const char *target,
2939                           svn_depth_t depth,
2940                           svn_boolean_t get_all,
2941                           svn_boolean_t no_ignore,
2942                           const apr_array_header_t *ignore_patterns,
2943                           svn_wc_status_func3_t status_func,
2944                           void *status_baton,
2945                           svn_cancel_func_t cancel_func,
2946                           void *cancel_baton,
2947                           svn_wc_traversal_info_t *traversal_info,
2948                           apr_pool_t *pool)
2949 {
2950   struct status4_wrapper_baton *swb = apr_palloc(pool, sizeof(*swb));
2951   svn_wc__db_t *wc_db;
2952   svn_wc_context_t *wc_ctx;
2953   const char *anchor_abspath;
2954
2955   swb->old_func = status_func;
2956   swb->old_baton = status_baton;
2957
2958   wc_db = svn_wc__adm_get_db(anchor);
2959
2960   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
2961                                          wc_db, pool));
2962
2963   swb->wc_ctx = wc_ctx;
2964
2965   anchor_abspath = svn_wc__adm_access_abspath(anchor);
2966
2967   if (!svn_dirent_is_absolute(svn_wc_adm_access_path(anchor)))
2968     {
2969       swb->anchor_abspath = anchor_abspath;
2970       swb->anchor_relpath = svn_wc_adm_access_path(anchor);
2971     }
2972   else
2973     {
2974       swb->anchor_abspath = NULL;
2975       swb->anchor_relpath = NULL;
2976     }
2977
2978   /* Before subversion 1.7 status always handled depth as sticky. 1.7 made
2979      the output of svn status by default match the result of what would be
2980      updated by a similar svn update. (Following the documentation) */
2981
2982   SVN_ERR(svn_wc_get_status_editor5(editor, edit_baton, set_locks_baton,
2983                                     edit_revision, wc_ctx, anchor_abspath,
2984                                     target, depth, get_all,
2985                                     no_ignore,
2986                                     (depth != svn_depth_unknown) /*as_sticky*/,
2987                                     FALSE /* server_performs_filtering */,
2988                                     ignore_patterns,
2989                                     status4_wrapper_func, swb,
2990                                     cancel_func, cancel_baton,
2991                                     pool, pool));
2992
2993   if (traversal_info)
2994     {
2995       const char *local_path = svn_wc_adm_access_path(anchor);
2996       const char *local_abspath = anchor_abspath;
2997       if (*target)
2998         {
2999           local_path = svn_dirent_join(local_path, target, pool);
3000           local_abspath = svn_dirent_join(local_abspath, target, pool);
3001         }
3002
3003       SVN_ERR(gather_traversal_info(wc_ctx, local_abspath, local_path, depth,
3004                                     traversal_info, TRUE, TRUE,
3005                                     pool));
3006     }
3007
3008   /* We can't destroy wc_ctx here, because the editor needs it while it's
3009      driven. */
3010   return SVN_NO_ERROR;
3011 }
3012
3013 struct status_editor3_compat_baton
3014 {
3015   svn_wc_status_func2_t old_func;
3016   void *old_baton;
3017 };
3018
3019 /* */
3020 static svn_error_t *
3021 status_editor3_compat_func(void *baton,
3022                            const char *path,
3023                            svn_wc_status2_t *status,
3024                            apr_pool_t *pool)
3025 {
3026   struct status_editor3_compat_baton *secb = baton;
3027
3028   secb->old_func(secb->old_baton, path, status);
3029   return SVN_NO_ERROR;
3030 }
3031
3032 svn_error_t *
3033 svn_wc_get_status_editor3(const svn_delta_editor_t **editor,
3034                           void **edit_baton,
3035                           void **set_locks_baton,
3036                           svn_revnum_t *edit_revision,
3037                           svn_wc_adm_access_t *anchor,
3038                           const char *target,
3039                           svn_depth_t depth,
3040                           svn_boolean_t get_all,
3041                           svn_boolean_t no_ignore,
3042                           const apr_array_header_t *ignore_patterns,
3043                           svn_wc_status_func2_t status_func,
3044                           void *status_baton,
3045                           svn_cancel_func_t cancel_func,
3046                           void *cancel_baton,
3047                           svn_wc_traversal_info_t *traversal_info,
3048                           apr_pool_t *pool)
3049 {
3050   /* This baton must live beyond this function. Alloc on heap.  */
3051   struct status_editor3_compat_baton *secb = apr_palloc(pool, sizeof(*secb));
3052
3053   secb->old_func = status_func;
3054   secb->old_baton = status_baton;
3055
3056   return svn_wc_get_status_editor4(editor, edit_baton, set_locks_baton,
3057                                    edit_revision, anchor, target, depth,
3058                                    get_all, no_ignore, ignore_patterns,
3059                                    status_editor3_compat_func, secb,
3060                                    cancel_func, cancel_baton, traversal_info,
3061                                    pool);
3062 }
3063
3064 svn_error_t *
3065 svn_wc_get_status_editor2(const svn_delta_editor_t **editor,
3066                           void **edit_baton,
3067                           void **set_locks_baton,
3068                           svn_revnum_t *edit_revision,
3069                           svn_wc_adm_access_t *anchor,
3070                           const char *target,
3071                           apr_hash_t *config,
3072                           svn_boolean_t recurse,
3073                           svn_boolean_t get_all,
3074                           svn_boolean_t no_ignore,
3075                           svn_wc_status_func2_t status_func,
3076                           void *status_baton,
3077                           svn_cancel_func_t cancel_func,
3078                           void *cancel_baton,
3079                           svn_wc_traversal_info_t *traversal_info,
3080                           apr_pool_t *pool)
3081 {
3082   apr_array_header_t *ignores;
3083
3084   SVN_ERR(svn_wc_get_default_ignores(&ignores, config, pool));
3085   return svn_wc_get_status_editor3(editor,
3086                                    edit_baton,
3087                                    set_locks_baton,
3088                                    edit_revision,
3089                                    anchor,
3090                                    target,
3091                                    SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse),
3092                                    get_all,
3093                                    no_ignore,
3094                                    ignores,
3095                                    status_func,
3096                                    status_baton,
3097                                    cancel_func,
3098                                    cancel_baton,
3099                                    traversal_info,
3100                                    pool);
3101 }
3102
3103
3104 /* Helpers for deprecated svn_wc_status_editor(), of type
3105    svn_wc_status_func2_t. */
3106 struct old_status_func_cb_baton
3107 {
3108   svn_wc_status_func_t original_func;
3109   void *original_baton;
3110 };
3111
3112 /* */
3113 static void old_status_func_cb(void *baton,
3114                                const char *path,
3115                                svn_wc_status2_t *status)
3116 {
3117   struct old_status_func_cb_baton *b = baton;
3118   svn_wc_status_t *stat = (svn_wc_status_t *) status;
3119
3120   b->original_func(b->original_baton, path, stat);
3121 }
3122
3123 svn_error_t *
3124 svn_wc_get_status_editor(const svn_delta_editor_t **editor,
3125                          void **edit_baton,
3126                          svn_revnum_t *edit_revision,
3127                          svn_wc_adm_access_t *anchor,
3128                          const char *target,
3129                          apr_hash_t *config,
3130                          svn_boolean_t recurse,
3131                          svn_boolean_t get_all,
3132                          svn_boolean_t no_ignore,
3133                          svn_wc_status_func_t status_func,
3134                          void *status_baton,
3135                          svn_cancel_func_t cancel_func,
3136                          void *cancel_baton,
3137                          svn_wc_traversal_info_t *traversal_info,
3138                          apr_pool_t *pool)
3139 {
3140   struct old_status_func_cb_baton *b = apr_pcalloc(pool, sizeof(*b));
3141   apr_array_header_t *ignores;
3142   b->original_func = status_func;
3143   b->original_baton = status_baton;
3144   SVN_ERR(svn_wc_get_default_ignores(&ignores, config, pool));
3145   return svn_wc_get_status_editor3(editor, edit_baton, NULL, edit_revision,
3146                                    anchor, target,
3147                                    SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse),
3148                                    get_all, no_ignore, ignores,
3149                                    old_status_func_cb, b,
3150                                    cancel_func, cancel_baton,
3151                                    traversal_info, pool);
3152 }
3153
3154 svn_error_t *
3155 svn_wc_status(svn_wc_status_t **status,
3156               const char *path,
3157               svn_wc_adm_access_t *adm_access,
3158               apr_pool_t *pool)
3159 {
3160   svn_wc_status2_t *stat2;
3161
3162   SVN_ERR(svn_wc_status2(&stat2, path, adm_access, pool));
3163   *status = (svn_wc_status_t *) stat2;
3164   return SVN_NO_ERROR;
3165 }
3166
3167
3168 static svn_wc_conflict_description_t *
3169 conflict_description_dup(const svn_wc_conflict_description_t *conflict,
3170                          apr_pool_t *pool)
3171 {
3172   svn_wc_conflict_description_t *new_conflict;
3173
3174   new_conflict = apr_pcalloc(pool, sizeof(*new_conflict));
3175
3176   /* Shallow copy all members. */
3177   *new_conflict = *conflict;
3178
3179   if (conflict->path)
3180     new_conflict->path = apr_pstrdup(pool, conflict->path);
3181   if (conflict->property_name)
3182     new_conflict->property_name = apr_pstrdup(pool, conflict->property_name);
3183   if (conflict->mime_type)
3184     new_conflict->mime_type = apr_pstrdup(pool, conflict->mime_type);
3185   /* NOTE: We cannot make a deep copy of adm_access. */
3186   if (conflict->base_file)
3187     new_conflict->base_file = apr_pstrdup(pool, conflict->base_file);
3188   if (conflict->their_file)
3189     new_conflict->their_file = apr_pstrdup(pool, conflict->their_file);
3190   if (conflict->my_file)
3191     new_conflict->my_file = apr_pstrdup(pool, conflict->my_file);
3192   if (conflict->merged_file)
3193     new_conflict->merged_file = apr_pstrdup(pool, conflict->merged_file);
3194   if (conflict->src_left_version)
3195     new_conflict->src_left_version =
3196       svn_wc_conflict_version_dup(conflict->src_left_version, pool);
3197   if (conflict->src_right_version)
3198     new_conflict->src_right_version =
3199       svn_wc_conflict_version_dup(conflict->src_right_version, pool);
3200
3201   return new_conflict;
3202 }
3203
3204
3205 svn_wc_status2_t *
3206 svn_wc_dup_status2(const svn_wc_status2_t *orig_stat,
3207                    apr_pool_t *pool)
3208 {
3209   svn_wc_status2_t *new_stat = apr_palloc(pool, sizeof(*new_stat));
3210
3211   /* Shallow copy all members. */
3212   *new_stat = *orig_stat;
3213
3214   /* Now go back and dup the deep items into this pool. */
3215   if (orig_stat->entry)
3216     new_stat->entry = svn_wc_entry_dup(orig_stat->entry, pool);
3217
3218   if (orig_stat->repos_lock)
3219     new_stat->repos_lock = svn_lock_dup(orig_stat->repos_lock, pool);
3220
3221   if (orig_stat->url)
3222     new_stat->url = apr_pstrdup(pool, orig_stat->url);
3223
3224   if (orig_stat->ood_last_cmt_author)
3225     new_stat->ood_last_cmt_author
3226       = apr_pstrdup(pool, orig_stat->ood_last_cmt_author);
3227
3228   if (orig_stat->tree_conflict)
3229     new_stat->tree_conflict
3230       = conflict_description_dup(orig_stat->tree_conflict, pool);
3231
3232   /* Return the new hotness. */
3233   return new_stat;
3234 }
3235
3236 svn_wc_status_t *
3237 svn_wc_dup_status(const svn_wc_status_t *orig_stat,
3238                   apr_pool_t *pool)
3239 {
3240   svn_wc_status_t *new_stat = apr_palloc(pool, sizeof(*new_stat));
3241
3242   /* Shallow copy all members. */
3243   *new_stat = *orig_stat;
3244
3245   /* Now go back and dup the deep item into this pool. */
3246   if (orig_stat->entry)
3247     new_stat->entry = svn_wc_entry_dup(orig_stat->entry, pool);
3248
3249   /* Return the new hotness. */
3250   return new_stat;
3251 }
3252
3253 svn_error_t *
3254 svn_wc_get_ignores(apr_array_header_t **patterns,
3255                    apr_hash_t *config,
3256                    svn_wc_adm_access_t *adm_access,
3257                    apr_pool_t *pool)
3258 {
3259   svn_wc_context_t *wc_ctx;
3260   const char *local_abspath;
3261
3262   SVN_ERR(svn_dirent_get_absolute(&local_abspath,
3263                                   svn_wc_adm_access_path(adm_access), pool));
3264
3265   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
3266                                          svn_wc__adm_get_db(adm_access),
3267                                          pool));
3268
3269   SVN_ERR(svn_wc_get_ignores2(patterns, wc_ctx, local_abspath, config, pool,
3270                               pool));
3271
3272   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
3273 }
3274
3275 svn_error_t *
3276 svn_wc_status2(svn_wc_status2_t **status,
3277                const char *path,
3278                svn_wc_adm_access_t *adm_access,
3279                apr_pool_t *pool)
3280 {
3281   const char *local_abspath;
3282   svn_wc_context_t *wc_ctx;
3283   svn_wc_status3_t *stat3;
3284
3285   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
3286   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
3287                                          svn_wc__adm_get_db(adm_access),
3288                                          pool));
3289
3290   SVN_ERR(svn_wc_status3(&stat3, wc_ctx, local_abspath, pool, pool));
3291   SVN_ERR(svn_wc__status2_from_3(status, stat3, wc_ctx, local_abspath,
3292                                  pool, pool));
3293
3294   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
3295 }
3296
3297
3298 /*** From update_editor.c ***/
3299
3300 svn_error_t *
3301 svn_wc_add_repos_file3(const char *dst_path,
3302                        svn_wc_adm_access_t *adm_access,
3303                        svn_stream_t *new_base_contents,
3304                        svn_stream_t *new_contents,
3305                        apr_hash_t *new_base_props,
3306                        apr_hash_t *new_props,
3307                        const char *copyfrom_url,
3308                        svn_revnum_t copyfrom_rev,
3309                        svn_cancel_func_t cancel_func,
3310                        void *cancel_baton,
3311                        svn_wc_notify_func2_t notify_func,
3312                        void *notify_baton,
3313                        apr_pool_t *pool)
3314 {
3315   const char *local_abspath;
3316   svn_wc_context_t *wc_ctx;
3317
3318   SVN_ERR(svn_dirent_get_absolute(&local_abspath, dst_path, pool));
3319   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
3320                                          svn_wc__adm_get_db(adm_access),
3321                                          pool));
3322
3323   SVN_ERR(svn_wc_add_repos_file4(wc_ctx,
3324                                  local_abspath,
3325                                  new_base_contents,
3326                                  new_contents,
3327                                  new_base_props,
3328                                  new_props,
3329                                  copyfrom_url,
3330                                  copyfrom_rev,
3331                                  cancel_func, cancel_baton,
3332                                  pool));
3333
3334   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
3335 }
3336
3337 svn_error_t *
3338 svn_wc_add_repos_file2(const char *dst_path,
3339                        svn_wc_adm_access_t *adm_access,
3340                        const char *new_text_base_path,
3341                        const char *new_text_path,
3342                        apr_hash_t *new_base_props,
3343                        apr_hash_t *new_props,
3344                        const char *copyfrom_url,
3345                        svn_revnum_t copyfrom_rev,
3346                        apr_pool_t *pool)
3347 {
3348   svn_stream_t *new_base_contents;
3349   svn_stream_t *new_contents = NULL;
3350
3351   SVN_ERR(svn_stream_open_readonly(&new_base_contents, new_text_base_path,
3352                                    pool, pool));
3353
3354   if (new_text_path)
3355     {
3356       /* NOTE: the specified path may *not* be under version control.
3357          It is most likely sitting in .svn/tmp/. Thus, we cannot use the
3358          typical WC functions to access "special", "keywords" or "EOL"
3359          information. We need to look at the properties given to us. */
3360
3361       /* If the new file is special, then we can simply open the given
3362          contents since it is already in normal form. */
3363       if (svn_hash_gets(new_props, SVN_PROP_SPECIAL) != NULL)
3364         {
3365           SVN_ERR(svn_stream_open_readonly(&new_contents, new_text_path,
3366                                            pool, pool));
3367         }
3368       else
3369         {
3370           /* The new text contents need to be detrans'd into normal form. */
3371           svn_subst_eol_style_t eol_style;
3372           const char *eol_str;
3373           apr_hash_t *keywords = NULL;
3374           svn_string_t *list;
3375
3376           list = svn_hash_gets(new_props, SVN_PROP_KEYWORDS);
3377           if (list != NULL)
3378             {
3379               /* Since we are detranslating, all of the keyword values
3380                  can be "". */
3381               SVN_ERR(svn_subst_build_keywords2(&keywords,
3382                                                 list->data,
3383                                                 "", "", 0, "",
3384                                                 pool));
3385               if (apr_hash_count(keywords) == 0)
3386                 keywords = NULL;
3387             }
3388
3389           svn_subst_eol_style_from_value(&eol_style, &eol_str,
3390                                          svn_hash_gets(new_props,
3391                                                        SVN_PROP_EOL_STYLE));
3392
3393           if (svn_subst_translation_required(eol_style, eol_str, keywords,
3394                                              FALSE, FALSE))
3395             {
3396               SVN_ERR(svn_subst_stream_detranslated(&new_contents,
3397                                                     new_text_path,
3398                                                     eol_style, eol_str,
3399                                                     FALSE,
3400                                                     keywords,
3401                                                     FALSE,
3402                                                     pool));
3403             }
3404           else
3405             {
3406               SVN_ERR(svn_stream_open_readonly(&new_contents, new_text_path,
3407                                                pool, pool));
3408             }
3409         }
3410     }
3411
3412   SVN_ERR(svn_wc_add_repos_file3(dst_path, adm_access,
3413                                  new_base_contents, new_contents,
3414                                  new_base_props, new_props,
3415                                  copyfrom_url, copyfrom_rev,
3416                                  NULL, NULL, NULL, NULL,
3417                                  pool));
3418
3419   /* The API contract states that the text files will be removed upon
3420      successful completion. add_repos_file3() does not remove the files
3421      since it only has streams on them. Toss 'em now. */
3422   svn_error_clear(svn_io_remove_file(new_text_base_path, pool));
3423   if (new_text_path)
3424     svn_error_clear(svn_io_remove_file(new_text_path, pool));
3425
3426   return SVN_NO_ERROR;
3427 }
3428
3429
3430 svn_error_t *
3431 svn_wc_add_repos_file(const char *dst_path,
3432                       svn_wc_adm_access_t *adm_access,
3433                       const char *new_text_path,
3434                       apr_hash_t *new_props,
3435                       const char *copyfrom_url,
3436                       svn_revnum_t copyfrom_rev,
3437                       apr_pool_t *pool)
3438 {
3439   return svn_wc_add_repos_file2(dst_path, adm_access,
3440                                 new_text_path, NULL,
3441                                 new_props, NULL,
3442                                 copyfrom_url, copyfrom_rev,
3443                                 pool);
3444 }
3445
3446 svn_error_t *
3447 svn_wc_get_actual_target(const char *path,
3448                          const char **anchor,
3449                          const char **target,
3450                          apr_pool_t *pool)
3451 {
3452   svn_wc_context_t *wc_ctx;
3453
3454   SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, pool, pool));
3455   SVN_ERR(svn_wc_get_actual_target2(anchor, target, wc_ctx, path, pool, pool));
3456
3457   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
3458 }
3459
3460 /* This function has no internal variant as its behavior on switched
3461    non-directories is not what you would expect. But this happens to
3462    be the legacy behavior of this function. */
3463 svn_error_t *
3464 svn_wc_is_wc_root2(svn_boolean_t *wc_root,
3465                    svn_wc_context_t *wc_ctx,
3466                    const char *local_abspath,
3467                    apr_pool_t *scratch_pool)
3468 {
3469   svn_boolean_t is_root;
3470   svn_boolean_t is_switched;
3471   svn_node_kind_t kind;
3472   svn_error_t *err;
3473   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
3474
3475   err = svn_wc__db_is_switched(&is_root, &is_switched, &kind,
3476                                wc_ctx->db, local_abspath, scratch_pool);
3477
3478   if (err)
3479     {
3480       if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND &&
3481           err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
3482         return svn_error_trace(err);
3483
3484       return svn_error_create(SVN_ERR_ENTRY_NOT_FOUND, err, err->message);
3485     }
3486
3487   *wc_root = is_root || (kind == svn_node_dir && is_switched);
3488
3489   return SVN_NO_ERROR;
3490 }
3491
3492 svn_error_t *
3493 svn_wc_is_wc_root(svn_boolean_t *wc_root,
3494                   const char *path,
3495                   svn_wc_adm_access_t *adm_access,
3496                   apr_pool_t *pool)
3497 {
3498   svn_wc_context_t *wc_ctx;
3499   const char *local_abspath;
3500   svn_error_t *err;
3501
3502   /* Subversion <= 1.6 said that '.' or a drive root is a WC root. */
3503   if (svn_path_is_empty(path) || svn_dirent_is_root(path, strlen(path)))
3504     {
3505       *wc_root = TRUE;
3506       return SVN_NO_ERROR;
3507     }
3508
3509   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
3510   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
3511                                          svn_wc__adm_get_db(adm_access),
3512                                          pool));
3513
3514   err = svn_wc_is_wc_root2(wc_root, wc_ctx, local_abspath, pool);
3515
3516   if (err
3517       && (err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY
3518           || err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND))
3519     {
3520       /* Subversion <= 1.6 said that an unversioned path is a WC root. */
3521       svn_error_clear(err);
3522       *wc_root = TRUE;
3523     }
3524   else
3525     SVN_ERR(err);
3526
3527   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
3528 }
3529
3530
3531 svn_error_t *
3532 svn_wc_get_update_editor4(const svn_delta_editor_t **editor,
3533                           void **edit_baton,
3534                           svn_revnum_t *target_revision,
3535                           svn_wc_context_t *wc_ctx,
3536                           const char *anchor_abspath,
3537                           const char *target_basename,
3538                           svn_boolean_t use_commit_times,
3539                           svn_depth_t depth,
3540                           svn_boolean_t depth_is_sticky,
3541                           svn_boolean_t allow_unver_obstructions,
3542                           svn_boolean_t adds_as_modification,
3543                           svn_boolean_t server_performs_filtering,
3544                           svn_boolean_t clean_checkout,
3545                           const char *diff3_cmd,
3546                           const apr_array_header_t *preserved_exts,
3547                           svn_wc_dirents_func_t fetch_dirents_func,
3548                           void *fetch_dirents_baton,
3549                           svn_wc_conflict_resolver_func2_t conflict_func,
3550                           void *conflict_baton,
3551                           svn_wc_external_update_t external_func,
3552                           void *external_baton,
3553                           svn_cancel_func_t cancel_func,
3554                           void *cancel_baton,
3555                           svn_wc_notify_func2_t notify_func,
3556                           void *notify_baton,
3557                           apr_pool_t *result_pool,
3558                           apr_pool_t *scratch_pool)
3559 {
3560   return svn_error_trace(
3561     svn_wc__get_update_editor(editor, edit_baton,
3562                               target_revision,
3563                               wc_ctx,
3564                               anchor_abspath,
3565                               target_basename, NULL,
3566                               use_commit_times,
3567                               depth, depth_is_sticky,
3568                               allow_unver_obstructions,
3569                               adds_as_modification,
3570                               server_performs_filtering,
3571                               clean_checkout,
3572                               diff3_cmd,
3573                               preserved_exts,
3574                               fetch_dirents_func, fetch_dirents_baton,
3575                               conflict_func, conflict_baton,
3576                               external_func, external_baton,
3577                               cancel_func, cancel_baton,
3578                               notify_func, notify_baton,
3579                               result_pool, scratch_pool));
3580 }
3581
3582
3583 svn_error_t *
3584 svn_wc_get_update_editor3(svn_revnum_t *target_revision,
3585                           svn_wc_adm_access_t *anchor,
3586                           const char *target,
3587                           svn_boolean_t use_commit_times,
3588                           svn_depth_t depth,
3589                           svn_boolean_t depth_is_sticky,
3590                           svn_boolean_t allow_unver_obstructions,
3591                           svn_wc_notify_func2_t notify_func,
3592                           void *notify_baton,
3593                           svn_cancel_func_t cancel_func,
3594                           void *cancel_baton,
3595                           svn_wc_conflict_resolver_func_t conflict_func,
3596                           void *conflict_baton,
3597                           svn_wc_get_file_t fetch_func,
3598                           void *fetch_baton,
3599                           const char *diff3_cmd,
3600                           const apr_array_header_t *preserved_exts,
3601                           const svn_delta_editor_t **editor,
3602                           void **edit_baton,
3603                           svn_wc_traversal_info_t *traversal_info,
3604                           apr_pool_t *pool)
3605 {
3606   svn_wc_context_t *wc_ctx;
3607   svn_wc__db_t *db = svn_wc__adm_get_db(anchor);
3608   svn_wc_external_update_t external_func = NULL;
3609   struct traversal_info_update_baton *eb = NULL;
3610   struct conflict_func_1to2_baton *cfw = NULL;
3611
3612   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, db, pool));
3613
3614   if (traversal_info)
3615     {
3616       eb = apr_palloc(pool, sizeof(*eb));
3617       eb->db = db;
3618       eb->traversal = traversal_info;
3619       external_func = traversal_info_update;
3620     }
3621
3622   if (conflict_func)
3623     {
3624       cfw = apr_pcalloc(pool, sizeof(*cfw));
3625       cfw->inner_func = conflict_func;
3626       cfw->inner_baton = conflict_baton;
3627     }
3628
3629   if (diff3_cmd)
3630     SVN_ERR(svn_path_cstring_to_utf8(&diff3_cmd, diff3_cmd, pool));
3631
3632   SVN_ERR(svn_wc_get_update_editor4(editor, edit_baton,
3633                                     target_revision,
3634                                     wc_ctx,
3635                                     svn_wc__adm_access_abspath(anchor),
3636                                     target,
3637                                     use_commit_times,
3638                                     depth, depth_is_sticky,
3639                                     allow_unver_obstructions,
3640                                     TRUE /* adds_as_modification */,
3641                                     FALSE /* server_performs_filtering */,
3642                                     FALSE /* clean_checkout */,
3643                                     diff3_cmd,
3644                                     preserved_exts,
3645                                     NULL, NULL, /* fetch_dirents_func, baton */
3646                                     conflict_func ? conflict_func_1to2_wrapper
3647                                                   : NULL,
3648                                     cfw,
3649                                     external_func, eb,
3650                                     cancel_func, cancel_baton,
3651                                     notify_func, notify_baton,
3652                                     pool, pool));
3653
3654   /* We can't destroy wc_ctx here, because the editor needs it while it's
3655      driven. */
3656   return SVN_NO_ERROR;
3657 }
3658
3659 svn_error_t *
3660 svn_wc_get_update_editor2(svn_revnum_t *target_revision,
3661                           svn_wc_adm_access_t *anchor,
3662                           const char *target,
3663                           svn_boolean_t use_commit_times,
3664                           svn_boolean_t recurse,
3665                           svn_wc_notify_func2_t notify_func,
3666                           void *notify_baton,
3667                           svn_cancel_func_t cancel_func,
3668                           void *cancel_baton,
3669                           const char *diff3_cmd,
3670                           const svn_delta_editor_t **editor,
3671                           void **edit_baton,
3672                           svn_wc_traversal_info_t *traversal_info,
3673                           apr_pool_t *pool)
3674 {
3675   return svn_wc_get_update_editor3(target_revision, anchor, target,
3676                                    use_commit_times,
3677                                    SVN_DEPTH_INFINITY_OR_FILES(recurse), FALSE,
3678                                    FALSE, notify_func, notify_baton,
3679                                    cancel_func, cancel_baton, NULL, NULL,
3680                                    NULL, NULL,
3681                                    diff3_cmd, NULL, editor, edit_baton,
3682                                    traversal_info, pool);
3683 }
3684
3685 svn_error_t *
3686 svn_wc_get_update_editor(svn_revnum_t *target_revision,
3687                          svn_wc_adm_access_t *anchor,
3688                          const char *target,
3689                          svn_boolean_t use_commit_times,
3690                          svn_boolean_t recurse,
3691                          svn_wc_notify_func_t notify_func,
3692                          void *notify_baton,
3693                          svn_cancel_func_t cancel_func,
3694                          void *cancel_baton,
3695                          const char *diff3_cmd,
3696                          const svn_delta_editor_t **editor,
3697                          void **edit_baton,
3698                          svn_wc_traversal_info_t *traversal_info,
3699                          apr_pool_t *pool)
3700 {
3701   /* This baton must live beyond this function. Alloc on heap.  */
3702   struct compat_notify_baton_t *nb = apr_palloc(pool, sizeof(*nb));
3703
3704   nb->func = notify_func;
3705   nb->baton = notify_baton;
3706
3707   return svn_wc_get_update_editor3(target_revision, anchor, target,
3708                                    use_commit_times,
3709                                    SVN_DEPTH_INFINITY_OR_FILES(recurse), FALSE,
3710                                    FALSE, compat_call_notify_func, nb,
3711                                    cancel_func, cancel_baton, NULL, NULL,
3712                                    NULL, NULL,
3713                                    diff3_cmd, NULL, editor, edit_baton,
3714                                    traversal_info, pool);
3715 }
3716
3717
3718 svn_error_t *
3719 svn_wc_get_switch_editor4(const svn_delta_editor_t **editor,
3720                           void **edit_baton,
3721                           svn_revnum_t *target_revision,
3722                           svn_wc_context_t *wc_ctx,
3723                           const char *anchor_abspath,
3724                           const char *target_basename,
3725                           const char *switch_url,
3726                           svn_boolean_t use_commit_times,
3727                           svn_depth_t depth,
3728                           svn_boolean_t depth_is_sticky,
3729                           svn_boolean_t allow_unver_obstructions,
3730                           svn_boolean_t server_performs_filtering,
3731                           const char *diff3_cmd,
3732                           const apr_array_header_t *preserved_exts,
3733                           svn_wc_dirents_func_t fetch_dirents_func,
3734                           void *fetch_dirents_baton,
3735                           svn_wc_conflict_resolver_func2_t conflict_func,
3736                           void *conflict_baton,
3737                           svn_wc_external_update_t external_func,
3738                           void *external_baton,
3739                           svn_cancel_func_t cancel_func,
3740                           void *cancel_baton,
3741                           svn_wc_notify_func2_t notify_func,
3742                           void *notify_baton,
3743                           apr_pool_t *result_pool,
3744                           apr_pool_t *scratch_pool)
3745 {
3746   return svn_error_trace(
3747     svn_wc__get_switch_editor(editor, edit_baton,
3748                               target_revision,
3749                               wc_ctx,
3750                               anchor_abspath, target_basename,
3751                               switch_url, NULL,
3752                               use_commit_times,
3753                               depth, depth_is_sticky,
3754                               allow_unver_obstructions,
3755                               server_performs_filtering,
3756                               diff3_cmd,
3757                               preserved_exts,
3758                               fetch_dirents_func, fetch_dirents_baton,
3759                               conflict_func, conflict_baton,
3760                               external_func, external_baton,
3761                               cancel_func, cancel_baton,
3762                               notify_func, notify_baton,
3763                               result_pool, scratch_pool));
3764 }
3765
3766
3767 svn_error_t *
3768 svn_wc_get_switch_editor3(svn_revnum_t *target_revision,
3769                           svn_wc_adm_access_t *anchor,
3770                           const char *target,
3771                           const char *switch_url,
3772                           svn_boolean_t use_commit_times,
3773                           svn_depth_t depth,
3774                           svn_boolean_t depth_is_sticky,
3775                           svn_boolean_t allow_unver_obstructions,
3776                           svn_wc_notify_func2_t notify_func,
3777                           void *notify_baton,
3778                           svn_cancel_func_t cancel_func,
3779                           void *cancel_baton,
3780                           svn_wc_conflict_resolver_func_t conflict_func,
3781                           void *conflict_baton,
3782                           const char *diff3_cmd,
3783                           const apr_array_header_t *preserved_exts,
3784                           const svn_delta_editor_t **editor,
3785                           void **edit_baton,
3786                           svn_wc_traversal_info_t *traversal_info,
3787                           apr_pool_t *pool)
3788 {
3789   svn_wc_context_t *wc_ctx;
3790   svn_wc__db_t *db = svn_wc__adm_get_db(anchor);
3791   svn_wc_external_update_t external_func = NULL;
3792   struct traversal_info_update_baton *eb = NULL;
3793   struct conflict_func_1to2_baton *cfw = NULL;
3794
3795   SVN_ERR_ASSERT(switch_url && svn_uri_is_canonical(switch_url, pool));
3796
3797   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, db, pool));
3798
3799   if (traversal_info)
3800     {
3801       eb = apr_palloc(pool, sizeof(*eb));
3802       eb->db = db;
3803       eb->traversal = traversal_info;
3804       external_func = traversal_info_update;
3805     }
3806
3807   if (conflict_func)
3808     {
3809       cfw = apr_pcalloc(pool, sizeof(*cfw));
3810       cfw->inner_func = conflict_func;
3811       cfw->inner_baton = conflict_baton;
3812     }
3813
3814   if (diff3_cmd)
3815     SVN_ERR(svn_path_cstring_to_utf8(&diff3_cmd, diff3_cmd, pool));
3816
3817   SVN_ERR(svn_wc_get_switch_editor4(editor, edit_baton,
3818                                     target_revision,
3819                                     wc_ctx,
3820                                     svn_wc__adm_access_abspath(anchor),
3821                                     target, switch_url,
3822                                     use_commit_times,
3823                                     depth, depth_is_sticky,
3824                                     allow_unver_obstructions,
3825                                     FALSE /* server_performs_filtering */,
3826                                     diff3_cmd,
3827                                     preserved_exts,
3828                                     NULL, NULL, /* fetch_dirents_func, baton */
3829                                     conflict_func ? conflict_func_1to2_wrapper
3830                                                   : NULL,
3831                                     cfw,
3832                                     external_func, eb,
3833                                     cancel_func, cancel_baton,
3834                                     notify_func, notify_baton,
3835                                     pool, pool));
3836
3837   /* We can't destroy wc_ctx here, because the editor needs it while it's
3838      driven. */
3839   return SVN_NO_ERROR;
3840 }
3841
3842 svn_error_t *
3843 svn_wc_get_switch_editor2(svn_revnum_t *target_revision,
3844                           svn_wc_adm_access_t *anchor,
3845                           const char *target,
3846                           const char *switch_url,
3847                           svn_boolean_t use_commit_times,
3848                           svn_boolean_t recurse,
3849                           svn_wc_notify_func2_t notify_func,
3850                           void *notify_baton,
3851                           svn_cancel_func_t cancel_func,
3852                           void *cancel_baton,
3853                           const char *diff3_cmd,
3854                           const svn_delta_editor_t **editor,
3855                           void **edit_baton,
3856                           svn_wc_traversal_info_t *traversal_info,
3857                           apr_pool_t *pool)
3858 {
3859   SVN_ERR_ASSERT(switch_url);
3860
3861   return svn_wc_get_switch_editor3(target_revision, anchor, target,
3862                                    switch_url, use_commit_times,
3863                                    SVN_DEPTH_INFINITY_OR_FILES(recurse), FALSE,
3864                                    FALSE, notify_func, notify_baton,
3865                                    cancel_func, cancel_baton,
3866                                    NULL, NULL, diff3_cmd,
3867                                    NULL, editor, edit_baton, traversal_info,
3868                                    pool);
3869 }
3870
3871 svn_error_t *
3872 svn_wc_get_switch_editor(svn_revnum_t *target_revision,
3873                          svn_wc_adm_access_t *anchor,
3874                          const char *target,
3875                          const char *switch_url,
3876                          svn_boolean_t use_commit_times,
3877                          svn_boolean_t recurse,
3878                          svn_wc_notify_func_t notify_func,
3879                          void *notify_baton,
3880                          svn_cancel_func_t cancel_func,
3881                          void *cancel_baton,
3882                          const char *diff3_cmd,
3883                          const svn_delta_editor_t **editor,
3884                          void **edit_baton,
3885                          svn_wc_traversal_info_t *traversal_info,
3886                          apr_pool_t *pool)
3887 {
3888   /* This baton must live beyond this function. Alloc on heap.  */
3889   struct compat_notify_baton_t *nb = apr_palloc(pool, sizeof(*nb));
3890
3891   nb->func = notify_func;
3892   nb->baton = notify_baton;
3893
3894   return svn_wc_get_switch_editor3(target_revision, anchor, target,
3895                                    switch_url, use_commit_times,
3896                                    SVN_DEPTH_INFINITY_OR_FILES(recurse), FALSE,
3897                                    FALSE, compat_call_notify_func, nb,
3898                                    cancel_func, cancel_baton,
3899                                    NULL, NULL, diff3_cmd,
3900                                    NULL, editor, edit_baton, traversal_info,
3901                                    pool);
3902 }
3903
3904
3905 svn_error_t *
3906 svn_wc_external_item_create(const svn_wc_external_item2_t **item,
3907                             apr_pool_t *pool)
3908 {
3909   *item = apr_pcalloc(pool, sizeof(svn_wc_external_item2_t));
3910   return SVN_NO_ERROR;
3911 }
3912
3913 svn_wc_external_item_t *
3914 svn_wc_external_item_dup(const svn_wc_external_item_t *item,
3915                          apr_pool_t *pool)
3916 {
3917   svn_wc_external_item_t *new_item = apr_palloc(pool, sizeof(*new_item));
3918
3919   *new_item = *item;
3920
3921   if (new_item->target_dir)
3922     new_item->target_dir = apr_pstrdup(pool, new_item->target_dir);
3923
3924   if (new_item->url)
3925     new_item->url = apr_pstrdup(pool, new_item->url);
3926
3927   return new_item;
3928 }
3929
3930
3931 svn_wc_traversal_info_t *
3932 svn_wc_init_traversal_info(apr_pool_t *pool)
3933 {
3934   svn_wc_traversal_info_t *ti = apr_palloc(pool, sizeof(*ti));
3935
3936   ti->pool           = pool;
3937   ti->externals_old  = apr_hash_make(pool);
3938   ti->externals_new  = apr_hash_make(pool);
3939   ti->depths         = apr_hash_make(pool);
3940
3941   return ti;
3942 }
3943
3944
3945 void
3946 svn_wc_edited_externals(apr_hash_t **externals_old,
3947                         apr_hash_t **externals_new,
3948                         svn_wc_traversal_info_t *traversal_info)
3949 {
3950   *externals_old = traversal_info->externals_old;
3951   *externals_new = traversal_info->externals_new;
3952 }
3953
3954
3955 void
3956 svn_wc_traversed_depths(apr_hash_t **depths,
3957                         svn_wc_traversal_info_t *traversal_info)
3958 {
3959   *depths = traversal_info->depths;
3960 }
3961
3962
3963 /*** From lock.c ***/
3964
3965 /* To preserve API compatibility with Subversion 1.0.0 */
3966 svn_error_t *
3967 svn_wc_adm_open(svn_wc_adm_access_t **adm_access,
3968                 svn_wc_adm_access_t *associated,
3969                 const char *path,
3970                 svn_boolean_t write_lock,
3971                 svn_boolean_t tree_lock,
3972                 apr_pool_t *pool)
3973 {
3974   return svn_wc_adm_open3(adm_access, associated, path, write_lock,
3975                           (tree_lock ? -1 : 0), NULL, NULL, pool);
3976 }
3977
3978 svn_error_t *
3979 svn_wc_adm_open2(svn_wc_adm_access_t **adm_access,
3980                  svn_wc_adm_access_t *associated,
3981                  const char *path,
3982                  svn_boolean_t write_lock,
3983                  int levels_to_lock,
3984                  apr_pool_t *pool)
3985 {
3986   return svn_wc_adm_open3(adm_access, associated, path, write_lock,
3987                           levels_to_lock, NULL, NULL, pool);
3988 }
3989
3990 svn_error_t *
3991 svn_wc_adm_probe_open(svn_wc_adm_access_t **adm_access,
3992                       svn_wc_adm_access_t *associated,
3993                       const char *path,
3994                       svn_boolean_t write_lock,
3995                       svn_boolean_t tree_lock,
3996                       apr_pool_t *pool)
3997 {
3998   return svn_wc_adm_probe_open3(adm_access, associated, path,
3999                                 write_lock, (tree_lock ? -1 : 0),
4000                                 NULL, NULL, pool);
4001 }
4002
4003
4004 svn_error_t *
4005 svn_wc_adm_probe_open2(svn_wc_adm_access_t **adm_access,
4006                        svn_wc_adm_access_t *associated,
4007                        const char *path,
4008                        svn_boolean_t write_lock,
4009                        int levels_to_lock,
4010                        apr_pool_t *pool)
4011 {
4012   return svn_wc_adm_probe_open3(adm_access, associated, path, write_lock,
4013                                 levels_to_lock, NULL, NULL, pool);
4014 }
4015
4016 svn_error_t *
4017 svn_wc_adm_probe_try2(svn_wc_adm_access_t **adm_access,
4018                       svn_wc_adm_access_t *associated,
4019                       const char *path,
4020                       svn_boolean_t write_lock,
4021                       int levels_to_lock,
4022                       apr_pool_t *pool)
4023 {
4024   return svn_wc_adm_probe_try3(adm_access, associated, path, write_lock,
4025                                levels_to_lock, NULL, NULL, pool);
4026 }
4027
4028 svn_error_t *
4029 svn_wc_adm_probe_try(svn_wc_adm_access_t **adm_access,
4030                      svn_wc_adm_access_t *associated,
4031                      const char *path,
4032                      svn_boolean_t write_lock,
4033                      svn_boolean_t tree_lock,
4034                      apr_pool_t *pool)
4035 {
4036   return svn_wc_adm_probe_try3(adm_access, associated, path, write_lock,
4037                                (tree_lock ? -1 : 0), NULL, NULL, pool);
4038 }
4039
4040 svn_error_t *
4041 svn_wc_adm_close(svn_wc_adm_access_t *adm_access)
4042 {
4043   /* This is the only pool we have access to. */
4044   apr_pool_t *scratch_pool = svn_wc_adm_access_pool(adm_access);
4045
4046   return svn_wc_adm_close2(adm_access, scratch_pool);
4047 }
4048
4049 svn_error_t *
4050 svn_wc_locked(svn_boolean_t *locked,
4051               const char *path,
4052               apr_pool_t *pool)
4053 {
4054   svn_wc_context_t *wc_ctx;
4055   const char *local_abspath;
4056
4057   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
4058   SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, pool, pool));
4059
4060   SVN_ERR(svn_wc_locked2(NULL, locked, wc_ctx, local_abspath, pool));
4061
4062   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4063 }
4064
4065 svn_error_t *
4066 svn_wc_check_wc(const char *path,
4067                 int *wc_format,
4068                 apr_pool_t *pool)
4069 {
4070   svn_wc_context_t *wc_ctx;
4071   const char *local_abspath;
4072
4073   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
4074   SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, pool, pool));
4075
4076   SVN_ERR(svn_wc_check_wc2(wc_format, wc_ctx, local_abspath, pool));
4077
4078   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4079 }
4080
4081
4082 /*** From translate.c ***/
4083
4084 svn_error_t *
4085 svn_wc_translated_file(const char **xlated_p,
4086                        const char *vfile,
4087                        svn_wc_adm_access_t *adm_access,
4088                        svn_boolean_t force_repair,
4089                        apr_pool_t *pool)
4090 {
4091   return svn_wc_translated_file2(xlated_p, vfile, vfile, adm_access,
4092                                  SVN_WC_TRANSLATE_TO_NF
4093                                  | (force_repair ?
4094                                     SVN_WC_TRANSLATE_FORCE_EOL_REPAIR : 0),
4095                                  pool);
4096 }
4097
4098 svn_error_t *
4099 svn_wc_translated_stream(svn_stream_t **stream,
4100                          const char *path,
4101                          const char *versioned_file,
4102                          svn_wc_adm_access_t *adm_access,
4103                          apr_uint32_t flags,
4104                          apr_pool_t *pool)
4105 {
4106   const char *local_abspath;
4107   const char *versioned_abspath;
4108
4109   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
4110   SVN_ERR(svn_dirent_get_absolute(&versioned_abspath, versioned_file, pool));
4111
4112   return svn_error_trace(
4113     svn_wc__internal_translated_stream(stream, svn_wc__adm_get_db(adm_access),
4114                                        local_abspath, versioned_abspath, flags,
4115                                        pool, pool));
4116 }
4117
4118 svn_error_t *
4119 svn_wc_translated_file2(const char **xlated_path,
4120                         const char *src,
4121                         const char *versioned_file,
4122                         svn_wc_adm_access_t *adm_access,
4123                         apr_uint32_t flags,
4124                         apr_pool_t *pool)
4125 {
4126   const char *versioned_abspath;
4127   const char *root;
4128   const char *tmp_root;
4129   const char *src_abspath;
4130
4131   SVN_ERR(svn_dirent_get_absolute(&versioned_abspath, versioned_file, pool));
4132   SVN_ERR(svn_dirent_get_absolute(&src_abspath, src, pool));
4133
4134   SVN_ERR(svn_wc__internal_translated_file(xlated_path, src_abspath,
4135                                            svn_wc__adm_get_db(adm_access),
4136                                            versioned_abspath,
4137                                            flags, NULL, NULL, pool, pool));
4138
4139   if (strcmp(*xlated_path, src_abspath) == 0)
4140     *xlated_path = src;
4141   else if (! svn_dirent_is_absolute(versioned_file))
4142     {
4143       SVN_ERR(svn_io_temp_dir(&tmp_root, pool));
4144       if (! svn_dirent_is_child(tmp_root, *xlated_path, pool))
4145         {
4146           SVN_ERR(svn_dirent_get_absolute(&root, "", pool));
4147
4148           if (svn_dirent_is_child(root, *xlated_path, pool))
4149             *xlated_path = svn_dirent_is_child(root, *xlated_path, pool);
4150         }
4151     }
4152
4153   return SVN_NO_ERROR;
4154 }
4155
4156 /*** From relocate.c ***/
4157 svn_error_t *
4158 svn_wc_relocate3(const char *path,
4159                  svn_wc_adm_access_t *adm_access,
4160                  const char *from,
4161                  const char *to,
4162                  svn_boolean_t recurse,
4163                  svn_wc_relocation_validator3_t validator,
4164                  void *validator_baton,
4165                  apr_pool_t *pool)
4166 {
4167   const char *local_abspath;
4168   svn_wc_context_t *wc_ctx;
4169
4170   if (! recurse)
4171     SVN_ERR(svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
4172                              _("Non-recursive relocation not supported")));
4173
4174   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
4175   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
4176                                          svn_wc__adm_get_db(adm_access),
4177                                          pool));
4178
4179   SVN_ERR(svn_wc_relocate4(wc_ctx, local_abspath, from, to,
4180                            validator, validator_baton, pool));
4181
4182   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4183 }
4184
4185 /* Compatibility baton and wrapper. */
4186 struct compat2_baton {
4187   svn_wc_relocation_validator2_t validator;
4188   void *baton;
4189 };
4190
4191 /* Compatibility baton and wrapper. */
4192 struct compat_baton {
4193   svn_wc_relocation_validator_t validator;
4194   void *baton;
4195 };
4196
4197 /* This implements svn_wc_relocate_validator3_t. */
4198 static svn_error_t *
4199 compat2_validator(void *baton,
4200                   const char *uuid,
4201                   const char *url,
4202                   const char *root_url,
4203                   apr_pool_t *pool)
4204 {
4205   struct compat2_baton *cb = baton;
4206   /* The old callback type doesn't set root_url. */
4207   return cb->validator(cb->baton, uuid,
4208                        (root_url ? root_url : url), (root_url != NULL),
4209                        pool);
4210 }
4211
4212 /* This implements svn_wc_relocate_validator3_t. */
4213 static svn_error_t *
4214 compat_validator(void *baton,
4215                  const char *uuid,
4216                  const char *url,
4217                  const char *root_url,
4218                  apr_pool_t *pool)
4219 {
4220   struct compat_baton *cb = baton;
4221   /* The old callback type doesn't allow uuid to be NULL. */
4222   if (uuid)
4223     return cb->validator(cb->baton, uuid, url);
4224   return SVN_NO_ERROR;
4225 }
4226
4227 svn_error_t *
4228 svn_wc_relocate2(const char *path,
4229                  svn_wc_adm_access_t *adm_access,
4230                  const char *from,
4231                  const char *to,
4232                  svn_boolean_t recurse,
4233                  svn_wc_relocation_validator2_t validator,
4234                  void *validator_baton,
4235                  apr_pool_t *pool)
4236 {
4237   struct compat2_baton cb;
4238
4239   cb.validator = validator;
4240   cb.baton = validator_baton;
4241
4242   return svn_wc_relocate3(path, adm_access, from, to, recurse,
4243                           compat2_validator, &cb, pool);
4244 }
4245
4246 svn_error_t *
4247 svn_wc_relocate(const char *path,
4248                 svn_wc_adm_access_t *adm_access,
4249                 const char *from,
4250                 const char *to,
4251                 svn_boolean_t recurse,
4252                 svn_wc_relocation_validator_t validator,
4253                 void *validator_baton,
4254                 apr_pool_t *pool)
4255 {
4256   struct compat_baton cb;
4257
4258   cb.validator = validator;
4259   cb.baton = validator_baton;
4260
4261   return svn_wc_relocate3(path, adm_access, from, to, recurse,
4262                           compat_validator, &cb, pool);
4263 }
4264
4265
4266 /*** From log.c / cleanup.c ***/
4267
4268 svn_error_t *
4269 svn_wc_cleanup3(svn_wc_context_t *wc_ctx,
4270                 const char *local_abspath,
4271                 svn_cancel_func_t cancel_func,
4272                 void *cancel_baton,
4273                 apr_pool_t *scratch_pool)
4274 {
4275   return svn_error_trace(
4276             svn_wc_cleanup4(wc_ctx,
4277                             local_abspath,
4278                             TRUE /* break_locks */,
4279                             TRUE /* fix_recorded_timestamps */,
4280                             TRUE /* clear_dav_cache */,
4281                             TRUE /* clean_pristines */,
4282                             cancel_func, cancel_baton,
4283                             NULL, NULL /* notify */,
4284                             scratch_pool));
4285 }
4286
4287 svn_error_t *
4288 svn_wc_cleanup2(const char *path,
4289                 const char *diff3_cmd,
4290                 svn_cancel_func_t cancel_func,
4291                 void *cancel_baton,
4292                 apr_pool_t *pool)
4293 {
4294   svn_wc_context_t *wc_ctx;
4295   const char *local_abspath;
4296
4297   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
4298   SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, pool, pool));
4299
4300   SVN_ERR(svn_wc_cleanup3(wc_ctx, local_abspath, cancel_func,
4301                           cancel_baton, pool));
4302
4303   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4304 }
4305
4306 svn_error_t *
4307 svn_wc_cleanup(const char *path,
4308                svn_wc_adm_access_t *optional_adm_access,
4309                const char *diff3_cmd,
4310                svn_cancel_func_t cancel_func,
4311                void *cancel_baton,
4312                apr_pool_t *pool)
4313 {
4314   return svn_wc_cleanup2(path, diff3_cmd, cancel_func, cancel_baton, pool);
4315 }
4316
4317 /*** From questions.c ***/
4318
4319 svn_error_t *
4320 svn_wc_has_binary_prop(svn_boolean_t *has_binary_prop,
4321                        const char *path,
4322                        svn_wc_adm_access_t *adm_access,
4323                        apr_pool_t *pool)
4324 {
4325   svn_wc__db_t *db = svn_wc__adm_get_db(adm_access);
4326   const char *local_abspath;
4327   const svn_string_t *value;
4328
4329   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
4330
4331   SVN_ERR(svn_wc__internal_propget(&value, db, local_abspath,
4332                                    SVN_PROP_MIME_TYPE,
4333                                    pool, pool));
4334
4335   if (value && (svn_mime_type_is_binary(value->data)))
4336     *has_binary_prop = TRUE;
4337   else
4338     *has_binary_prop = FALSE;
4339
4340   return SVN_NO_ERROR;
4341 }
4342
4343 svn_error_t *
4344 svn_wc_conflicted_p2(svn_boolean_t *text_conflicted_p,
4345                      svn_boolean_t *prop_conflicted_p,
4346                      svn_boolean_t *tree_conflicted_p,
4347                      const char *path,
4348                      svn_wc_adm_access_t *adm_access,
4349                      apr_pool_t *pool)
4350 {
4351   const char *local_abspath;
4352   svn_wc_context_t *wc_ctx;
4353   svn_error_t *err;
4354
4355   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
4356   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
4357                                          svn_wc__adm_get_db(adm_access),
4358                                          pool));
4359
4360   err = svn_wc_conflicted_p3(text_conflicted_p, prop_conflicted_p,
4361                              tree_conflicted_p, wc_ctx, local_abspath, pool);
4362
4363   if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
4364     {
4365       svn_error_clear(err);
4366
4367       if (text_conflicted_p)
4368         *text_conflicted_p = FALSE;
4369       if (prop_conflicted_p)
4370         *prop_conflicted_p = FALSE;
4371       if (tree_conflicted_p)
4372         *tree_conflicted_p = FALSE;
4373     }
4374   else if (err)
4375     return err;
4376
4377   return SVN_NO_ERROR;
4378 }
4379
4380 svn_error_t *
4381 svn_wc_conflicted_p(svn_boolean_t *text_conflicted_p,
4382                     svn_boolean_t *prop_conflicted_p,
4383                     const char *dir_path,
4384                     const svn_wc_entry_t *entry,
4385                     apr_pool_t *pool)
4386 {
4387   svn_node_kind_t kind;
4388   const char *path;
4389
4390   *text_conflicted_p = FALSE;
4391   *prop_conflicted_p = FALSE;
4392
4393   if (entry->conflict_old)
4394     {
4395       path = svn_dirent_join(dir_path, entry->conflict_old, pool);
4396       SVN_ERR(svn_io_check_path(path, &kind, pool));
4397       *text_conflicted_p = (kind == svn_node_file);
4398     }
4399
4400   if ((! *text_conflicted_p) && (entry->conflict_new))
4401     {
4402       path = svn_dirent_join(dir_path, entry->conflict_new, pool);
4403       SVN_ERR(svn_io_check_path(path, &kind, pool));
4404       *text_conflicted_p = (kind == svn_node_file);
4405     }
4406
4407   if ((! *text_conflicted_p) && (entry->conflict_wrk))
4408     {
4409       path = svn_dirent_join(dir_path, entry->conflict_wrk, pool);
4410       SVN_ERR(svn_io_check_path(path, &kind, pool));
4411       *text_conflicted_p = (kind == svn_node_file);
4412     }
4413
4414   if (entry->prejfile)
4415     {
4416       path = svn_dirent_join(dir_path, entry->prejfile, pool);
4417       SVN_ERR(svn_io_check_path(path, &kind, pool));
4418       *prop_conflicted_p = (kind == svn_node_file);
4419     }
4420
4421   return SVN_NO_ERROR;
4422 }
4423
4424 svn_error_t *
4425 svn_wc_text_modified_p(svn_boolean_t *modified_p,
4426                        const char *filename,
4427                        svn_boolean_t force_comparison,
4428                        svn_wc_adm_access_t *adm_access,
4429                        apr_pool_t *pool)
4430 {
4431   svn_wc_context_t *wc_ctx;
4432   svn_wc__db_t *db = svn_wc__adm_get_db(adm_access);
4433   const char *local_abspath;
4434
4435   SVN_ERR(svn_dirent_get_absolute(&local_abspath, filename, pool));
4436   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, db, pool));
4437
4438   SVN_ERR(svn_wc_text_modified_p2(modified_p, wc_ctx, local_abspath,
4439                                   force_comparison, pool));
4440
4441   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4442 }
4443
4444
4445 /*** From copy.c ***/
4446 svn_error_t *
4447 svn_wc_copy2(const char *src,
4448              svn_wc_adm_access_t *dst_parent,
4449              const char *dst_basename,
4450              svn_cancel_func_t cancel_func,
4451              void *cancel_baton,
4452              svn_wc_notify_func2_t notify_func,
4453              void *notify_baton,
4454              apr_pool_t *pool)
4455 {
4456   svn_wc_context_t *wc_ctx;
4457   svn_wc__db_t *wc_db = svn_wc__adm_get_db(dst_parent);
4458   const char *src_abspath;
4459   const char *dst_abspath;
4460
4461   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, wc_db, pool));
4462   SVN_ERR(svn_dirent_get_absolute(&src_abspath, src, pool));
4463
4464   dst_abspath = svn_dirent_join(svn_wc__adm_access_abspath(dst_parent),
4465                                 dst_basename, pool);
4466
4467   SVN_ERR(svn_wc_copy3(wc_ctx,
4468                        src_abspath,
4469                        dst_abspath,
4470                        FALSE /* metadata_only */,
4471                        cancel_func, cancel_baton,
4472                        notify_func, notify_baton,
4473                        pool));
4474
4475   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4476 }
4477
4478 svn_error_t *
4479 svn_wc_copy(const char *src_path,
4480             svn_wc_adm_access_t *dst_parent,
4481             const char *dst_basename,
4482             svn_cancel_func_t cancel_func,
4483             void *cancel_baton,
4484             svn_wc_notify_func_t notify_func,
4485             void *notify_baton,
4486             apr_pool_t *pool)
4487 {
4488   struct compat_notify_baton_t nb;
4489
4490   nb.func = notify_func;
4491   nb.baton = notify_baton;
4492
4493   return svn_wc_copy2(src_path, dst_parent, dst_basename, cancel_func,
4494                       cancel_baton, compat_call_notify_func,
4495                       &nb, pool);
4496 }
4497
4498
4499 /*** From merge.c ***/
4500
4501 svn_error_t *
4502 svn_wc_merge4(enum svn_wc_merge_outcome_t *merge_outcome,
4503               svn_wc_context_t *wc_ctx,
4504               const char *left_abspath,
4505               const char *right_abspath,
4506               const char *target_abspath,
4507               const char *left_label,
4508               const char *right_label,
4509               const char *target_label,
4510               const svn_wc_conflict_version_t *left_version,
4511               const svn_wc_conflict_version_t *right_version,
4512               svn_boolean_t dry_run,
4513               const char *diff3_cmd,
4514               const apr_array_header_t *merge_options,
4515               const apr_array_header_t *prop_diff,
4516               svn_wc_conflict_resolver_func2_t conflict_func,
4517               void *conflict_baton,
4518               svn_cancel_func_t cancel_func,
4519               void *cancel_baton,
4520               apr_pool_t *scratch_pool)
4521 {
4522   return svn_error_trace(
4523             svn_wc_merge5(merge_outcome,
4524                           NULL /* merge_props_outcome */,
4525                           wc_ctx,
4526                           left_abspath,
4527                           right_abspath,
4528                           target_abspath,
4529                           left_label,
4530                           right_label,
4531                           target_label,
4532                           left_version,
4533                           right_version,
4534                           dry_run,
4535                           diff3_cmd,
4536                           merge_options,
4537                           NULL /* original_props */,
4538                           prop_diff,
4539                           conflict_func, conflict_baton,
4540                           cancel_func, cancel_baton,
4541                           scratch_pool));
4542 }
4543
4544 svn_error_t *
4545 svn_wc_merge3(enum svn_wc_merge_outcome_t *merge_outcome,
4546               const char *left,
4547               const char *right,
4548               const char *merge_target,
4549               svn_wc_adm_access_t *adm_access,
4550               const char *left_label,
4551               const char *right_label,
4552               const char *target_label,
4553               svn_boolean_t dry_run,
4554               const char *diff3_cmd,
4555               const apr_array_header_t *merge_options,
4556               const apr_array_header_t *prop_diff,
4557               svn_wc_conflict_resolver_func_t conflict_func,
4558               void *conflict_baton,
4559               apr_pool_t *pool)
4560 {
4561   svn_wc_context_t *wc_ctx;
4562   svn_wc__db_t *db = svn_wc__adm_get_db(adm_access);
4563   const char *left_abspath, *right_abspath, *target_abspath;
4564   struct conflict_func_1to2_baton cfw;
4565
4566   SVN_ERR(svn_dirent_get_absolute(&left_abspath, left, pool));
4567   SVN_ERR(svn_dirent_get_absolute(&right_abspath, right, pool));
4568   SVN_ERR(svn_dirent_get_absolute(&target_abspath, merge_target, pool));
4569
4570   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */, db, pool));
4571
4572   cfw.inner_func = conflict_func;
4573   cfw.inner_baton = conflict_baton;
4574
4575   if (diff3_cmd)
4576     SVN_ERR(svn_path_cstring_to_utf8(&diff3_cmd, diff3_cmd, pool));
4577
4578   SVN_ERR(svn_wc_merge4(merge_outcome,
4579                         wc_ctx,
4580                         left_abspath,
4581                         right_abspath,
4582                         target_abspath,
4583                         left_label,
4584                         right_label,
4585                         target_label,
4586                         NULL,
4587                         NULL,
4588                         dry_run,
4589                         diff3_cmd,
4590                         merge_options,
4591                         prop_diff,
4592                         conflict_func ? conflict_func_1to2_wrapper : NULL,
4593                         &cfw,
4594                         NULL, NULL,
4595                         pool));
4596
4597   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4598 }
4599
4600 svn_error_t *
4601 svn_wc_merge2(enum svn_wc_merge_outcome_t *merge_outcome,
4602               const char *left,
4603               const char *right,
4604               const char *merge_target,
4605               svn_wc_adm_access_t *adm_access,
4606               const char *left_label,
4607               const char *right_label,
4608               const char *target_label,
4609               svn_boolean_t dry_run,
4610               const char *diff3_cmd,
4611               const apr_array_header_t *merge_options,
4612               apr_pool_t *pool)
4613 {
4614   return svn_wc_merge3(merge_outcome,
4615                        left, right, merge_target, adm_access,
4616                        left_label, right_label, target_label,
4617                        dry_run, diff3_cmd, merge_options, NULL,
4618                        NULL, NULL, pool);
4619 }
4620
4621 svn_error_t *
4622 svn_wc_merge(const char *left,
4623              const char *right,
4624              const char *merge_target,
4625              svn_wc_adm_access_t *adm_access,
4626              const char *left_label,
4627              const char *right_label,
4628              const char *target_label,
4629              svn_boolean_t dry_run,
4630              enum svn_wc_merge_outcome_t *merge_outcome,
4631              const char *diff3_cmd,
4632              apr_pool_t *pool)
4633 {
4634   return svn_wc_merge3(merge_outcome,
4635                        left, right, merge_target, adm_access,
4636                        left_label, right_label, target_label,
4637                        dry_run, diff3_cmd, NULL, NULL, NULL,
4638                        NULL, pool);
4639 }
4640
4641
4642 /*** From util.c ***/
4643
4644 svn_wc_conflict_version_t *
4645 svn_wc_conflict_version_create(const char *repos_url,
4646                                const char *path_in_repos,
4647                                svn_revnum_t peg_rev,
4648                                svn_node_kind_t node_kind,
4649                                apr_pool_t *pool)
4650 {
4651   return svn_wc_conflict_version_create2(repos_url, NULL, path_in_repos,
4652                                          peg_rev, node_kind, pool);
4653 }
4654
4655 svn_wc_conflict_description_t *
4656 svn_wc_conflict_description_create_text(const char *path,
4657                                         svn_wc_adm_access_t *adm_access,
4658                                         apr_pool_t *pool)
4659 {
4660   svn_wc_conflict_description_t *conflict;
4661
4662   conflict = apr_pcalloc(pool, sizeof(*conflict));
4663   conflict->path = path;
4664   conflict->node_kind = svn_node_file;
4665   conflict->kind = svn_wc_conflict_kind_text;
4666   conflict->access = adm_access;
4667   conflict->action = svn_wc_conflict_action_edit;
4668   conflict->reason = svn_wc_conflict_reason_edited;
4669   return conflict;
4670 }
4671
4672 svn_wc_conflict_description_t *
4673 svn_wc_conflict_description_create_prop(const char *path,
4674                                         svn_wc_adm_access_t *adm_access,
4675                                         svn_node_kind_t node_kind,
4676                                         const char *property_name,
4677                                         apr_pool_t *pool)
4678 {
4679   svn_wc_conflict_description_t *conflict;
4680
4681   conflict = apr_pcalloc(pool, sizeof(*conflict));
4682   conflict->path = path;
4683   conflict->node_kind = node_kind;
4684   conflict->kind = svn_wc_conflict_kind_property;
4685   conflict->access = adm_access;
4686   conflict->property_name = property_name;
4687   return conflict;
4688 }
4689
4690 svn_wc_conflict_description_t *
4691 svn_wc_conflict_description_create_tree(
4692                             const char *path,
4693                             svn_wc_adm_access_t *adm_access,
4694                             svn_node_kind_t node_kind,
4695                             svn_wc_operation_t operation,
4696                             svn_wc_conflict_version_t *src_left_version,
4697                             svn_wc_conflict_version_t *src_right_version,
4698                             apr_pool_t *pool)
4699 {
4700   svn_wc_conflict_description_t *conflict;
4701
4702   conflict = apr_pcalloc(pool, sizeof(*conflict));
4703   conflict->path = path;
4704   conflict->node_kind = node_kind;
4705   conflict->kind = svn_wc_conflict_kind_tree;
4706   conflict->access = adm_access;
4707   conflict->operation = operation;
4708   conflict->src_left_version = src_left_version;
4709   conflict->src_right_version = src_right_version;
4710   return conflict;
4711 }
4712
4713
4714 /*** From revision_status.c ***/
4715
4716 svn_error_t *
4717 svn_wc_revision_status(svn_wc_revision_status_t **result_p,
4718                        const char *wc_path,
4719                        const char *trail_url,
4720                        svn_boolean_t committed,
4721                        svn_cancel_func_t cancel_func,
4722                        void *cancel_baton,
4723                        apr_pool_t *pool)
4724 {
4725   svn_wc_context_t *wc_ctx;
4726   const char *local_abspath;
4727
4728   SVN_ERR(svn_dirent_get_absolute(&local_abspath, wc_path, pool));
4729   SVN_ERR(svn_wc_context_create(&wc_ctx, NULL /* config */, pool, pool));
4730
4731   SVN_ERR(svn_wc_revision_status2(result_p, wc_ctx, local_abspath, trail_url,
4732                                   committed, cancel_func, cancel_baton, pool,
4733                                   pool));
4734
4735   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4736 }
4737
4738 /*** From crop.c ***/
4739 svn_error_t *
4740 svn_wc_crop_tree(svn_wc_adm_access_t *anchor,
4741                  const char *target,
4742                  svn_depth_t depth,
4743                  svn_wc_notify_func2_t notify_func,
4744                  void *notify_baton,
4745                  svn_cancel_func_t cancel_func,
4746                  void *cancel_baton,
4747                  apr_pool_t *pool)
4748 {
4749   svn_wc_context_t *wc_ctx;
4750   svn_wc__db_t *db = svn_wc__adm_get_db(anchor);
4751   const char *local_abspath;
4752
4753   local_abspath = svn_dirent_join(svn_wc__adm_access_abspath(anchor),
4754                                   target, pool);
4755
4756   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, db, pool));
4757
4758   if (depth == svn_depth_exclude)
4759     {
4760       SVN_ERR(svn_wc_exclude(wc_ctx,
4761                              local_abspath,
4762                              cancel_func, cancel_baton,
4763                              notify_func, notify_baton,
4764                              pool));
4765     }
4766   else
4767     {
4768       SVN_ERR(svn_wc_crop_tree2(wc_ctx,
4769                                 local_abspath,
4770                                 depth,
4771                                 cancel_func, cancel_baton,
4772                                 notify_func, notify_baton,
4773                                 pool));
4774     }
4775
4776   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4777 }
4778
4779 svn_error_t *
4780 svn_wc_move(svn_wc_context_t *wc_ctx,
4781             const char *src_abspath,
4782             const char *dst_abspath,
4783             svn_boolean_t metadata_only,
4784             svn_cancel_func_t cancel_func,
4785             void *cancel_baton,
4786             svn_wc_notify_func2_t notify_func,
4787             void *notify_baton,
4788             apr_pool_t *scratch_pool)
4789 {
4790   return svn_error_trace(svn_wc__move2(wc_ctx, src_abspath, dst_abspath,
4791                                        metadata_only,
4792                                        TRUE, /* allow_mixed_revisions */
4793                                        cancel_func, cancel_baton,
4794                                        notify_func, notify_baton,
4795                                        scratch_pool));
4796 }
4797
4798 svn_error_t *
4799 svn_wc_read_kind(svn_node_kind_t *kind,
4800                  svn_wc_context_t *wc_ctx,
4801                  const char *abspath,
4802                  svn_boolean_t show_hidden,
4803                  apr_pool_t *scratch_pool)
4804 {
4805   return svn_error_trace(
4806           svn_wc_read_kind2(kind,
4807                             wc_ctx, abspath,
4808                             TRUE /* show_deleted */,
4809                             show_hidden,
4810                             scratch_pool));
4811 }
4812
4813 svn_wc_conflict_description2_t *
4814 svn_wc__conflict_description2_dup(const svn_wc_conflict_description2_t *conflict,
4815                                   apr_pool_t *pool)
4816 {
4817   return svn_wc_conflict_description2_dup(conflict, pool);
4818 }