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