]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/subversion/subversion/libsvn_wc/deprecated.c
Update Subversion and dependencies to 1.14.0 LTS.
[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_revert5(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_boolean_t clear_changelists,
1100                svn_boolean_t metadata_only,
1101                svn_cancel_func_t cancel_func,
1102                void *cancel_baton,
1103                svn_wc_notify_func2_t notify_func,
1104                void *notify_baton,
1105                apr_pool_t *scratch_pool)
1106 {
1107   SVN_ERR(svn_wc_revert6(wc_ctx, local_abspath,
1108                          depth,
1109                          use_commit_times,
1110                          changelist_filter,
1111                          clear_changelists,
1112                          metadata_only,
1113                          TRUE /*added_keep_local*/,
1114                          cancel_func, cancel_baton,
1115                          notify_func, notify_baton,
1116                          scratch_pool));
1117   return SVN_NO_ERROR;
1118 }
1119
1120 svn_error_t *
1121 svn_wc_revert4(svn_wc_context_t *wc_ctx,
1122                const char *local_abspath,
1123                svn_depth_t depth,
1124                svn_boolean_t use_commit_times,
1125                const apr_array_header_t *changelist_filter,
1126                svn_cancel_func_t cancel_func,
1127                void *cancel_baton,
1128                svn_wc_notify_func2_t notify_func,
1129                void *notify_baton,
1130                apr_pool_t *scratch_pool)
1131 {
1132   return svn_error_trace(svn_wc_revert5(wc_ctx, local_abspath,
1133                                         depth,
1134                                         use_commit_times,
1135                                         changelist_filter,
1136                                         FALSE /* clear_changelists */,
1137                                         FALSE /* metadata_only */,
1138                                         cancel_func, cancel_baton,
1139                                         notify_func, notify_baton,
1140                                         scratch_pool));
1141 }
1142
1143 svn_error_t *
1144 svn_wc_revert3(const char *path,
1145                svn_wc_adm_access_t *parent_access,
1146                svn_depth_t depth,
1147                svn_boolean_t use_commit_times,
1148                const apr_array_header_t *changelist_filter,
1149                svn_cancel_func_t cancel_func,
1150                void *cancel_baton,
1151                svn_wc_notify_func2_t notify_func,
1152                void *notify_baton,
1153                apr_pool_t *pool)
1154 {
1155   svn_wc_context_t *wc_ctx;
1156   svn_wc__db_t *wc_db = svn_wc__adm_get_db(parent_access);
1157   const char *local_abspath;
1158
1159   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, wc_db, pool));
1160   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
1161
1162   SVN_ERR(svn_wc_revert4(wc_ctx,
1163                          local_abspath,
1164                          depth,
1165                          use_commit_times,
1166                          changelist_filter,
1167                          cancel_func, cancel_baton,
1168                          notify_func, notify_baton,
1169                          pool));
1170
1171   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
1172 }
1173
1174 svn_error_t *
1175 svn_wc_revert2(const char *path,
1176                svn_wc_adm_access_t *parent_access,
1177                svn_boolean_t recursive,
1178                svn_boolean_t use_commit_times,
1179                svn_cancel_func_t cancel_func,
1180                void *cancel_baton,
1181                svn_wc_notify_func2_t notify_func,
1182                void *notify_baton,
1183                apr_pool_t *pool)
1184 {
1185   return svn_wc_revert3(path, parent_access,
1186                         SVN_DEPTH_INFINITY_OR_EMPTY(recursive),
1187                         use_commit_times, NULL, cancel_func, cancel_baton,
1188                         notify_func, notify_baton, pool);
1189 }
1190
1191 svn_error_t *
1192 svn_wc_revert(const char *path,
1193               svn_wc_adm_access_t *parent_access,
1194               svn_boolean_t recursive,
1195               svn_boolean_t use_commit_times,
1196               svn_cancel_func_t cancel_func,
1197               void *cancel_baton,
1198               svn_wc_notify_func_t notify_func,
1199               void *notify_baton,
1200               apr_pool_t *pool)
1201 {
1202   struct compat_notify_baton_t nb;
1203
1204   nb.func = notify_func;
1205   nb.baton = notify_baton;
1206
1207   return svn_wc_revert2(path, parent_access, recursive, use_commit_times,
1208                         cancel_func, cancel_baton,
1209                         compat_call_notify_func, &nb, pool);
1210 }
1211
1212 svn_error_t *
1213 svn_wc_remove_from_revision_control(svn_wc_adm_access_t *adm_access,
1214                                     const char *name,
1215                                     svn_boolean_t destroy_wf,
1216                                     svn_boolean_t instant_error,
1217                                     svn_cancel_func_t cancel_func,
1218                                     void *cancel_baton,
1219                                     apr_pool_t *pool)
1220 {
1221   svn_wc_context_t *wc_ctx;
1222   svn_wc__db_t *wc_db = svn_wc__adm_get_db(adm_access);
1223   const char *local_abspath = svn_dirent_join(
1224                                     svn_wc__adm_access_abspath(adm_access),
1225                                     name,
1226                                     pool);
1227
1228   /* name must be an entry in adm_access, fail if not */
1229   SVN_ERR_ASSERT(strcmp(svn_dirent_basename(name, NULL), name) == 0);
1230   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, wc_db, pool));
1231
1232   SVN_ERR(svn_wc_remove_from_revision_control2(wc_ctx,
1233                                                local_abspath,
1234                                                destroy_wf,
1235                                                instant_error,
1236                                                cancel_func, cancel_baton,
1237                                                pool));
1238
1239   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
1240 }
1241
1242 svn_error_t *
1243 svn_wc_resolved_conflict4(const char *path,
1244                           svn_wc_adm_access_t *adm_access,
1245                           svn_boolean_t resolve_text,
1246                           svn_boolean_t resolve_props,
1247                           svn_boolean_t resolve_tree,
1248                           svn_depth_t depth,
1249                           svn_wc_conflict_choice_t conflict_choice,
1250                           svn_wc_notify_func2_t notify_func,
1251                           void *notify_baton,
1252                           svn_cancel_func_t cancel_func,
1253                           void *cancel_baton,
1254                           apr_pool_t *pool)
1255 {
1256   svn_wc_context_t *wc_ctx;
1257   svn_wc__db_t *wc_db = svn_wc__adm_get_db(adm_access);
1258   const char *local_abspath;
1259
1260   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
1261   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, wc_db, pool));
1262
1263   SVN_ERR(svn_wc_resolved_conflict5(wc_ctx,
1264                                     local_abspath,
1265                                     depth,
1266                                     resolve_text,
1267                                     resolve_props ? "" : NULL,
1268                                     resolve_tree,
1269                                     conflict_choice,
1270                                     cancel_func,
1271                                     cancel_baton,
1272                                     notify_func,
1273                                     notify_baton,
1274                                     pool));
1275
1276   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
1277
1278 }
1279
1280 svn_error_t *
1281 svn_wc_resolved_conflict(const char *path,
1282                          svn_wc_adm_access_t *adm_access,
1283                          svn_boolean_t resolve_text,
1284                          svn_boolean_t resolve_props,
1285                          svn_boolean_t recurse,
1286                          svn_wc_notify_func_t notify_func,
1287                          void *notify_baton,
1288                          apr_pool_t *pool)
1289 {
1290   struct compat_notify_baton_t nb;
1291
1292   nb.func = notify_func;
1293   nb.baton = notify_baton;
1294
1295   return svn_wc_resolved_conflict2(path, adm_access,
1296                                    resolve_text, resolve_props, recurse,
1297                                    compat_call_notify_func, &nb,
1298                                    NULL, NULL, pool);
1299
1300 }
1301
1302 svn_error_t *
1303 svn_wc_resolved_conflict2(const char *path,
1304                           svn_wc_adm_access_t *adm_access,
1305                           svn_boolean_t resolve_text,
1306                           svn_boolean_t resolve_props,
1307                           svn_boolean_t recurse,
1308                           svn_wc_notify_func2_t notify_func,
1309                           void *notify_baton,
1310                           svn_cancel_func_t cancel_func,
1311                           void *cancel_baton,
1312                           apr_pool_t *pool)
1313 {
1314   return svn_wc_resolved_conflict3(path, adm_access, resolve_text,
1315                                    resolve_props,
1316                                    SVN_DEPTH_INFINITY_OR_EMPTY(recurse),
1317                                    svn_wc_conflict_choose_merged,
1318                                    notify_func, notify_baton, cancel_func,
1319                                    cancel_baton, pool);
1320 }
1321
1322 svn_error_t *
1323 svn_wc_resolved_conflict3(const char *path,
1324                           svn_wc_adm_access_t *adm_access,
1325                           svn_boolean_t resolve_text,
1326                           svn_boolean_t resolve_props,
1327                           svn_depth_t depth,
1328                           svn_wc_conflict_choice_t conflict_choice,
1329                           svn_wc_notify_func2_t notify_func,
1330                           void *notify_baton,
1331                           svn_cancel_func_t cancel_func,
1332                           void *cancel_baton,
1333                           apr_pool_t *pool)
1334 {
1335   return svn_wc_resolved_conflict4(path, adm_access, resolve_text,
1336                                    resolve_props, FALSE, depth,
1337                                    svn_wc_conflict_choose_merged,
1338                                    notify_func, notify_baton, cancel_func,
1339                                    cancel_baton, pool);
1340 }
1341
1342 svn_error_t *
1343 svn_wc_add_lock(const char *path,
1344                 const svn_lock_t *lock,
1345                 svn_wc_adm_access_t *adm_access,
1346                 apr_pool_t *pool)
1347 {
1348   const char *local_abspath;
1349   svn_wc_context_t *wc_ctx;
1350
1351   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
1352   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
1353                                          svn_wc__adm_get_db(adm_access),
1354                                          pool));
1355
1356   SVN_ERR(svn_wc_add_lock2(wc_ctx, local_abspath, lock, pool));
1357
1358   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
1359 }
1360
1361 svn_error_t *
1362 svn_wc_remove_lock(const char *path,
1363                    svn_wc_adm_access_t *adm_access,
1364                    apr_pool_t *pool)
1365 {
1366   const char *local_abspath;
1367   svn_wc_context_t *wc_ctx;
1368
1369   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
1370   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
1371                                          svn_wc__adm_get_db(adm_access),
1372                                          pool));
1373
1374   SVN_ERR(svn_wc_remove_lock2(wc_ctx, local_abspath, pool));
1375
1376   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
1377
1378 }
1379
1380 svn_error_t *
1381 svn_wc_get_ancestry(char **url,
1382                     svn_revnum_t *rev,
1383                     const char *path,
1384                     svn_wc_adm_access_t *adm_access,
1385                     apr_pool_t *pool)
1386 {
1387   const char *local_abspath;
1388   const svn_wc_entry_t *entry;
1389
1390   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
1391
1392   SVN_ERR(svn_wc__get_entry(&entry, svn_wc__adm_get_db(adm_access),
1393                             local_abspath, FALSE,
1394                             svn_node_unknown,
1395                             pool, pool));
1396
1397   if (url)
1398     *url = apr_pstrdup(pool, entry->url);
1399
1400   if (rev)
1401     *rev = entry->revision;
1402
1403   return SVN_NO_ERROR;
1404 }
1405
1406 svn_error_t *
1407 svn_wc_set_changelist(const char *path,
1408                       const char *changelist,
1409                       svn_wc_adm_access_t *adm_access,
1410                       svn_cancel_func_t cancel_func,
1411                       void *cancel_baton,
1412                       svn_wc_notify_func2_t notify_func,
1413                       void *notify_baton,
1414                       apr_pool_t *pool)
1415 {
1416   const char *local_abspath;
1417   svn_wc_context_t *wc_ctx;
1418
1419   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
1420   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
1421                                          svn_wc__adm_get_db(adm_access),
1422                                          pool));
1423
1424   SVN_ERR(svn_wc_set_changelist2(wc_ctx, local_abspath, changelist,
1425                                  svn_depth_empty, NULL,
1426                                  cancel_func, cancel_baton, notify_func,
1427                                  notify_baton, pool));
1428
1429   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
1430 }
1431
1432
1433 /*** From diff.c ***/
1434 /* Used to wrap svn_wc_diff_callbacks_t. */
1435 struct diff_callbacks_wrapper_baton {
1436   const svn_wc_diff_callbacks_t *callbacks;
1437   void *baton;
1438 };
1439
1440 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t. */
1441 static svn_error_t *
1442 wrap_3to1_file_changed(svn_wc_adm_access_t *adm_access,
1443                        svn_wc_notify_state_t *contentstate,
1444                        svn_wc_notify_state_t *propstate,
1445                        svn_boolean_t *tree_conflicted,
1446                        const char *path,
1447                        const char *tmpfile1,
1448                        const char *tmpfile2,
1449                        svn_revnum_t rev1,
1450                        svn_revnum_t rev2,
1451                        const char *mimetype1,
1452                        const char *mimetype2,
1453                        const apr_array_header_t *propchanges,
1454                        apr_hash_t *originalprops,
1455                        void *diff_baton)
1456 {
1457   struct diff_callbacks_wrapper_baton *b = diff_baton;
1458
1459   if (tree_conflicted)
1460     *tree_conflicted = FALSE;
1461
1462   if (tmpfile2 != NULL)
1463     SVN_ERR(b->callbacks->file_changed(adm_access, contentstate, path,
1464                                        tmpfile1, tmpfile2,
1465                                        rev1, rev2, mimetype1, mimetype2,
1466                                        b->baton));
1467   if (propchanges->nelts > 0)
1468     SVN_ERR(b->callbacks->props_changed(adm_access, propstate, path,
1469                                         propchanges, originalprops,
1470                                         b->baton));
1471
1472   return SVN_NO_ERROR;
1473 }
1474
1475 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t. */
1476 static svn_error_t *
1477 wrap_3to1_file_added(svn_wc_adm_access_t *adm_access,
1478                      svn_wc_notify_state_t *contentstate,
1479                      svn_wc_notify_state_t *propstate,
1480                      svn_boolean_t *tree_conflicted,
1481                      const char *path,
1482                      const char *tmpfile1,
1483                      const char *tmpfile2,
1484                      svn_revnum_t rev1,
1485                      svn_revnum_t rev2,
1486                      const char *mimetype1,
1487                      const char *mimetype2,
1488                      const apr_array_header_t *propchanges,
1489                      apr_hash_t *originalprops,
1490                      void *diff_baton)
1491 {
1492   struct diff_callbacks_wrapper_baton *b = diff_baton;
1493
1494   if (tree_conflicted)
1495     *tree_conflicted = FALSE;
1496
1497   SVN_ERR(b->callbacks->file_added(adm_access, contentstate, path,
1498                                    tmpfile1, tmpfile2, rev1, rev2,
1499                                    mimetype1, mimetype2, b->baton));
1500   if (propchanges->nelts > 0)
1501     SVN_ERR(b->callbacks->props_changed(adm_access, propstate, path,
1502                                         propchanges, originalprops,
1503                                         b->baton));
1504
1505   return SVN_NO_ERROR;
1506 }
1507
1508 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t. */
1509 static svn_error_t *
1510 wrap_3to1_file_deleted(svn_wc_adm_access_t *adm_access,
1511                        svn_wc_notify_state_t *state,
1512                        svn_boolean_t *tree_conflicted,
1513                        const char *path,
1514                        const char *tmpfile1,
1515                        const char *tmpfile2,
1516                        const char *mimetype1,
1517                        const char *mimetype2,
1518                        apr_hash_t *originalprops,
1519                        void *diff_baton)
1520 {
1521   struct diff_callbacks_wrapper_baton *b = diff_baton;
1522
1523   if (tree_conflicted)
1524     *tree_conflicted = FALSE;
1525
1526   SVN_ERR_ASSERT(originalprops);
1527
1528   return b->callbacks->file_deleted(adm_access, state, path,
1529                                     tmpfile1, tmpfile2, mimetype1, mimetype2,
1530                                     b->baton);
1531 }
1532
1533 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t. */
1534 static svn_error_t *
1535 wrap_3to1_dir_added(svn_wc_adm_access_t *adm_access,
1536                     svn_wc_notify_state_t *state,
1537                     svn_boolean_t *tree_conflicted,
1538                     const char *path,
1539                     svn_revnum_t rev,
1540                     void *diff_baton)
1541 {
1542   struct diff_callbacks_wrapper_baton *b = diff_baton;
1543
1544   if (tree_conflicted)
1545     *tree_conflicted = FALSE;
1546
1547   return b->callbacks->dir_added(adm_access, state, path, rev, b->baton);
1548 }
1549
1550 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t. */
1551 static svn_error_t *
1552 wrap_3to1_dir_deleted(svn_wc_adm_access_t *adm_access,
1553                       svn_wc_notify_state_t *state,
1554                       svn_boolean_t *tree_conflicted,
1555                       const char *path,
1556                       void *diff_baton)
1557 {
1558   struct diff_callbacks_wrapper_baton *b = diff_baton;
1559
1560   if (tree_conflicted)
1561     *tree_conflicted = FALSE;
1562
1563   return b->callbacks->dir_deleted(adm_access, state, path, b->baton);
1564 }
1565
1566 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t. */
1567 static svn_error_t *
1568 wrap_3to1_dir_props_changed(svn_wc_adm_access_t *adm_access,
1569                             svn_wc_notify_state_t *state,
1570                             svn_boolean_t *tree_conflicted,
1571                             const char *path,
1572                             const apr_array_header_t *propchanges,
1573                             apr_hash_t *originalprops,
1574                             void *diff_baton)
1575 {
1576   struct diff_callbacks_wrapper_baton *b = diff_baton;
1577
1578   if (tree_conflicted)
1579     *tree_conflicted = FALSE;
1580
1581   return b->callbacks->props_changed(adm_access, state, path, propchanges,
1582                                      originalprops, b->baton);
1583 }
1584
1585 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t
1586    and svn_wc_diff_callbacks2_t. */
1587 static svn_error_t *
1588 wrap_3to1or2_dir_opened(svn_wc_adm_access_t *adm_access,
1589                         svn_boolean_t *tree_conflicted,
1590                         const char *path,
1591                         svn_revnum_t rev,
1592                         void *diff_baton)
1593 {
1594   if (tree_conflicted)
1595     *tree_conflicted = FALSE;
1596   /* Do nothing. */
1597   return SVN_NO_ERROR;
1598 }
1599
1600 /* An svn_wc_diff_callbacks3_t function for wrapping svn_wc_diff_callbacks_t
1601    and svn_wc_diff_callbacks2_t. */
1602 static svn_error_t *
1603 wrap_3to1or2_dir_closed(svn_wc_adm_access_t *adm_access,
1604                         svn_wc_notify_state_t *propstate,
1605                         svn_wc_notify_state_t *contentstate,
1606                         svn_boolean_t *tree_conflicted,
1607                         const char *path,
1608                         void *diff_baton)
1609 {
1610   if (contentstate)
1611     *contentstate = svn_wc_notify_state_unknown;
1612   if (propstate)
1613     *propstate = svn_wc_notify_state_unknown;
1614   if (tree_conflicted)
1615     *tree_conflicted = FALSE;
1616   /* Do nothing. */
1617   return SVN_NO_ERROR;
1618 }
1619
1620 /* Used to wrap svn_diff_callbacks_t as an svn_wc_diff_callbacks3_t. */
1621 static struct svn_wc_diff_callbacks3_t diff_callbacks_wrapper = {
1622   wrap_3to1_file_changed,
1623   wrap_3to1_file_added,
1624   wrap_3to1_file_deleted,
1625   wrap_3to1_dir_added,
1626   wrap_3to1_dir_deleted,
1627   wrap_3to1_dir_props_changed,
1628   wrap_3to1or2_dir_opened,
1629   wrap_3to1or2_dir_closed
1630 };
1631
1632
1633
1634 /* Used to wrap svn_wc_diff_callbacks2_t. */
1635 struct diff_callbacks2_wrapper_baton {
1636   const svn_wc_diff_callbacks2_t *callbacks2;
1637   void *baton;
1638 };
1639
1640 /* An svn_wc_diff_callbacks3_t function for wrapping
1641  * svn_wc_diff_callbacks2_t. */
1642 static svn_error_t *
1643 wrap_3to2_file_changed(svn_wc_adm_access_t *adm_access,
1644                        svn_wc_notify_state_t *contentstate,
1645                        svn_wc_notify_state_t *propstate,
1646                        svn_boolean_t *tree_conflicted,
1647                        const char *path,
1648                        const char *tmpfile1,
1649                        const char *tmpfile2,
1650                        svn_revnum_t rev1,
1651                        svn_revnum_t rev2,
1652                        const char *mimetype1,
1653                        const char *mimetype2,
1654                        const apr_array_header_t *propchanges,
1655                        apr_hash_t *originalprops,
1656                        void *diff_baton)
1657 {
1658   struct diff_callbacks2_wrapper_baton *b = diff_baton;
1659
1660   if (tree_conflicted)
1661     *tree_conflicted = FALSE;
1662
1663   return b->callbacks2->file_changed(adm_access, contentstate, propstate,
1664                                      path, tmpfile1, tmpfile2,
1665                                      rev1, rev2, mimetype1, mimetype2,
1666                                      propchanges, originalprops, b->baton);
1667 }
1668
1669 /* An svn_wc_diff_callbacks3_t function for wrapping
1670  * svn_wc_diff_callbacks2_t. */
1671 static svn_error_t *
1672 wrap_3to2_file_added(svn_wc_adm_access_t *adm_access,
1673                      svn_wc_notify_state_t *contentstate,
1674                      svn_wc_notify_state_t *propstate,
1675                      svn_boolean_t *tree_conflicted,
1676                      const char *path,
1677                      const char *tmpfile1,
1678                      const char *tmpfile2,
1679                      svn_revnum_t rev1,
1680                      svn_revnum_t rev2,
1681                      const char *mimetype1,
1682                      const char *mimetype2,
1683                      const apr_array_header_t *propchanges,
1684                      apr_hash_t *originalprops,
1685                      void *diff_baton)
1686 {
1687   struct diff_callbacks2_wrapper_baton *b = diff_baton;
1688
1689   if (tree_conflicted)
1690     *tree_conflicted = FALSE;
1691
1692   return b->callbacks2->file_added(adm_access, contentstate, propstate, path,
1693                                    tmpfile1, tmpfile2, rev1, rev2,
1694                                    mimetype1, mimetype2, propchanges,
1695                                    originalprops, b->baton);
1696 }
1697
1698 /* An svn_wc_diff_callbacks3_t function for wrapping
1699  * svn_wc_diff_callbacks2_t. */
1700 static svn_error_t *
1701 wrap_3to2_file_deleted(svn_wc_adm_access_t *adm_access,
1702                        svn_wc_notify_state_t *state,
1703                        svn_boolean_t *tree_conflicted,
1704                        const char *path,
1705                        const char *tmpfile1,
1706                        const char *tmpfile2,
1707                        const char *mimetype1,
1708                        const char *mimetype2,
1709                        apr_hash_t *originalprops,
1710                        void *diff_baton)
1711 {
1712   struct diff_callbacks2_wrapper_baton *b = diff_baton;
1713
1714   if (tree_conflicted)
1715     *tree_conflicted = FALSE;
1716
1717   return b->callbacks2->file_deleted(adm_access, state, path,
1718                                      tmpfile1, tmpfile2, mimetype1, mimetype2,
1719                                      originalprops, b->baton);
1720 }
1721
1722 /* An svn_wc_diff_callbacks3_t function for wrapping
1723  * svn_wc_diff_callbacks2_t. */
1724 static svn_error_t *
1725 wrap_3to2_dir_added(svn_wc_adm_access_t *adm_access,
1726                     svn_wc_notify_state_t *state,
1727                     svn_boolean_t *tree_conflicted,
1728                     const char *path,
1729                     svn_revnum_t rev,
1730                     void *diff_baton)
1731 {
1732   struct diff_callbacks2_wrapper_baton *b = diff_baton;
1733
1734   if (tree_conflicted)
1735     *tree_conflicted = FALSE;
1736
1737   return b->callbacks2->dir_added(adm_access, state, path, rev, b->baton);
1738 }
1739
1740 /* An svn_wc_diff_callbacks3_t function for wrapping
1741  * svn_wc_diff_callbacks2_t. */
1742 static svn_error_t *
1743 wrap_3to2_dir_deleted(svn_wc_adm_access_t *adm_access,
1744                       svn_wc_notify_state_t *state,
1745                       svn_boolean_t *tree_conflicted,
1746                       const char *path,
1747                       void *diff_baton)
1748 {
1749   struct diff_callbacks2_wrapper_baton *b = diff_baton;
1750
1751   if (tree_conflicted)
1752     *tree_conflicted = FALSE;
1753
1754   return b->callbacks2->dir_deleted(adm_access, state, path, b->baton);
1755 }
1756
1757 /* An svn_wc_diff_callbacks3_t function for wrapping
1758  * svn_wc_diff_callbacks2_t. */
1759 static svn_error_t *
1760 wrap_3to2_dir_props_changed(svn_wc_adm_access_t *adm_access,
1761                             svn_wc_notify_state_t *state,
1762                             svn_boolean_t *tree_conflicted,
1763                             const char *path,
1764                             const apr_array_header_t *propchanges,
1765                             apr_hash_t *originalprops,
1766                             void *diff_baton)
1767 {
1768   struct diff_callbacks2_wrapper_baton *b = diff_baton;
1769
1770   if (tree_conflicted)
1771     *tree_conflicted = FALSE;
1772
1773   return b->callbacks2->dir_props_changed(adm_access, state, path, propchanges,
1774                                           originalprops, b->baton);
1775 }
1776
1777 /* Used to wrap svn_diff_callbacks2_t as an svn_wc_diff_callbacks3_t. */
1778 static struct svn_wc_diff_callbacks3_t diff_callbacks2_wrapper = {
1779   wrap_3to2_file_changed,
1780   wrap_3to2_file_added,
1781   wrap_3to2_file_deleted,
1782   wrap_3to2_dir_added,
1783   wrap_3to2_dir_deleted,
1784   wrap_3to2_dir_props_changed,
1785   wrap_3to1or2_dir_opened,
1786   wrap_3to1or2_dir_closed
1787 };
1788
1789
1790
1791 /* Used to wrap svn_wc_diff_callbacks3_t. */
1792 struct diff_callbacks3_wrapper_baton {
1793   const svn_wc_diff_callbacks3_t *callbacks3;
1794   svn_wc__db_t *db;
1795   void *baton;
1796   const char *anchor;
1797   const char *anchor_abspath;
1798 };
1799
1800 static svn_error_t *
1801 wrap_4to3_file_opened(svn_boolean_t *tree_conflicted,
1802                       svn_boolean_t *skip,
1803                       const char *path,
1804                       svn_revnum_t rev,
1805                       void *diff_baton,
1806                       apr_pool_t *scratch_pool)
1807 {
1808   return SVN_NO_ERROR;
1809 }
1810
1811 /* An svn_wc_diff_callbacks4_t function for wrapping
1812  * svn_wc_diff_callbacks3_t. */
1813 static svn_error_t *
1814 wrap_4to3_file_changed(svn_wc_notify_state_t *contentstate,
1815                        svn_wc_notify_state_t *propstate,
1816                        svn_boolean_t *tree_conflicted,
1817                        const char *path,
1818                        const char *tmpfile1,
1819                        const char *tmpfile2,
1820                        svn_revnum_t rev1,
1821                        svn_revnum_t rev2,
1822                        const char *mimetype1,
1823                        const char *mimetype2,
1824                        const apr_array_header_t *propchanges,
1825                        apr_hash_t *originalprops,
1826                        void *diff_baton,
1827                        apr_pool_t *scratch_pool)
1828 {
1829   struct diff_callbacks3_wrapper_baton *b = diff_baton;
1830   svn_wc_adm_access_t *adm_access;
1831   const char *dir = svn_relpath_dirname(path, scratch_pool);
1832
1833   adm_access = svn_wc__adm_retrieve_internal2(
1834                         b->db,
1835                         svn_dirent_join(b->anchor_abspath, dir, scratch_pool),
1836                         scratch_pool);
1837
1838   return b->callbacks3->file_changed(adm_access, contentstate, propstate,
1839                                      tree_conflicted,
1840                                      svn_dirent_join(b->anchor, path,
1841                                                      scratch_pool),
1842                                      tmpfile1, tmpfile2,
1843                                      rev1, rev2, mimetype1, mimetype2,
1844                                      propchanges, originalprops, b->baton);
1845 }
1846
1847 /* An svn_wc_diff_callbacks4_t function for wrapping
1848  * svn_wc_diff_callbacks3_t. */
1849 static svn_error_t *
1850 wrap_4to3_file_added(svn_wc_notify_state_t *contentstate,
1851                      svn_wc_notify_state_t *propstate,
1852                      svn_boolean_t *tree_conflicted,
1853                      const char *path,
1854                      const char *tmpfile1,
1855                      const char *tmpfile2,
1856                      svn_revnum_t rev1,
1857                      svn_revnum_t rev2,
1858                      const char *mimetype1,
1859                      const char *mimetype2,
1860                      const char *copyfrom_path,
1861                      svn_revnum_t copyfrom_revision,
1862                      const apr_array_header_t *propchanges,
1863                      apr_hash_t *originalprops,
1864                      void *diff_baton,
1865                      apr_pool_t *scratch_pool)
1866 {
1867   struct diff_callbacks3_wrapper_baton *b = diff_baton;
1868   svn_wc_adm_access_t *adm_access;
1869   const char *dir = svn_relpath_dirname(path, scratch_pool);
1870
1871   adm_access = svn_wc__adm_retrieve_internal2(
1872                         b->db,
1873                         svn_dirent_join(b->anchor_abspath, dir, scratch_pool),
1874                         scratch_pool);
1875
1876   return b->callbacks3->file_added(adm_access, contentstate, propstate,
1877                                    tree_conflicted,
1878                                    svn_dirent_join(b->anchor, path,
1879                                                    scratch_pool),
1880                                    tmpfile1, tmpfile2,
1881                                    rev1, rev2, mimetype1, mimetype2,
1882                                    propchanges, originalprops, b->baton);
1883 }
1884
1885 /* An svn_wc_diff_callbacks4_t function for wrapping
1886  * svn_wc_diff_callbacks3_t. */
1887 static svn_error_t *
1888 wrap_4to3_file_deleted(svn_wc_notify_state_t *state,
1889                        svn_boolean_t *tree_conflicted,
1890                        const char *path,
1891                        const char *tmpfile1,
1892                        const char *tmpfile2,
1893                        const char *mimetype1,
1894                        const char *mimetype2,
1895                        apr_hash_t *originalprops,
1896                        void *diff_baton,
1897                        apr_pool_t *scratch_pool)
1898 {
1899   struct diff_callbacks3_wrapper_baton *b = diff_baton;
1900   svn_wc_adm_access_t *adm_access;
1901   const char *dir = svn_relpath_dirname(path, scratch_pool);
1902
1903   adm_access = svn_wc__adm_retrieve_internal2(
1904                         b->db,
1905                         svn_dirent_join(b->anchor_abspath, dir, scratch_pool),
1906                         scratch_pool);
1907
1908   return b->callbacks3->file_deleted(adm_access, state, tree_conflicted,
1909                                      svn_dirent_join(b->anchor, path,
1910                                                      scratch_pool),
1911                                      tmpfile1, tmpfile2,
1912                                      mimetype1, mimetype2, originalprops,
1913                                      b->baton);
1914 }
1915
1916 /* An svn_wc_diff_callbacks4_t function for wrapping
1917  * svn_wc_diff_callbacks3_t. */
1918 static svn_error_t *
1919 wrap_4to3_dir_added(svn_wc_notify_state_t *state,
1920                     svn_boolean_t *tree_conflicted,
1921                     svn_boolean_t *skip,
1922                     svn_boolean_t *skip_children,
1923                     const char *path,
1924                     svn_revnum_t rev,
1925                     const char *copyfrom_path,
1926                     svn_revnum_t copyfrom_revision,
1927                     void *diff_baton,
1928                     apr_pool_t *scratch_pool)
1929 {
1930   struct diff_callbacks3_wrapper_baton *b = diff_baton;
1931   svn_wc_adm_access_t *adm_access;
1932
1933   adm_access = svn_wc__adm_retrieve_internal2(
1934                         b->db,
1935                         svn_dirent_join(b->anchor_abspath, path, scratch_pool),
1936                         scratch_pool);
1937
1938   return b->callbacks3->dir_added(adm_access, state, tree_conflicted,
1939                                   svn_dirent_join(b->anchor, path,
1940                                                      scratch_pool),
1941                                   rev, b->baton);
1942 }
1943
1944 /* An svn_wc_diff_callbacks4_t function for wrapping
1945  * svn_wc_diff_callbacks3_t. */
1946 static svn_error_t *
1947 wrap_4to3_dir_deleted(svn_wc_notify_state_t *state,
1948                       svn_boolean_t *tree_conflicted,
1949                       const char *path,
1950                       void *diff_baton,
1951                       apr_pool_t *scratch_pool)
1952 {
1953   struct diff_callbacks3_wrapper_baton *b = diff_baton;
1954   svn_wc_adm_access_t *adm_access;
1955
1956   adm_access = svn_wc__adm_retrieve_internal2(
1957                         b->db,
1958                         svn_dirent_join(b->anchor_abspath, path, scratch_pool),
1959                         scratch_pool);
1960
1961   return b->callbacks3->dir_deleted(adm_access, state, tree_conflicted,
1962                                     svn_dirent_join(b->anchor, path,
1963                                                      scratch_pool),
1964                                     b->baton);
1965 }
1966
1967 /* An svn_wc_diff_callbacks4_t function for wrapping
1968  * svn_wc_diff_callbacks3_t. */
1969 static svn_error_t *
1970 wrap_4to3_dir_props_changed(svn_wc_notify_state_t *propstate,
1971                             svn_boolean_t *tree_conflicted,
1972                             const char *path,
1973                             svn_boolean_t dir_was_added,
1974                             const apr_array_header_t *propchanges,
1975                             apr_hash_t *original_props,
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
1987   return b->callbacks3->dir_props_changed(adm_access, propstate,
1988                                           tree_conflicted,
1989                                           svn_dirent_join(b->anchor, path,
1990                                                      scratch_pool),
1991                                           propchanges, original_props,
1992                                           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_opened(svn_boolean_t *tree_conflicted,
1999                      svn_boolean_t *skip,
2000                      svn_boolean_t *skip_children,
2001                      const char *path,
2002                      svn_revnum_t rev,
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   if (skip_children)
2014     *skip_children = FALSE;
2015
2016   return b->callbacks3->dir_opened(adm_access, tree_conflicted,
2017                                    svn_dirent_join(b->anchor, path,
2018                                                      scratch_pool),
2019                                    rev, b->baton);
2020 }
2021
2022 /* An svn_wc_diff_callbacks4_t function for wrapping
2023  * svn_wc_diff_callbacks3_t. */
2024 static svn_error_t *
2025 wrap_4to3_dir_closed(svn_wc_notify_state_t *contentstate,
2026                      svn_wc_notify_state_t *propstate,
2027                      svn_boolean_t *tree_conflicted,
2028                      const char *path,
2029                      svn_boolean_t dir_was_added,
2030                      void *diff_baton,
2031                      apr_pool_t *scratch_pool)
2032 {
2033   struct diff_callbacks3_wrapper_baton *b = diff_baton;
2034   svn_wc_adm_access_t *adm_access;
2035
2036   adm_access = svn_wc__adm_retrieve_internal2(
2037                         b->db,
2038                         svn_dirent_join(b->anchor_abspath, path, scratch_pool),
2039                         scratch_pool);
2040
2041   return b->callbacks3->dir_closed(adm_access, contentstate, propstate,
2042                                    tree_conflicted,
2043                                    svn_dirent_join(b->anchor, path,
2044                                                      scratch_pool),
2045                                    b->baton);
2046 }
2047
2048
2049 /* Used to wrap svn_diff_callbacks3_t as an svn_wc_diff_callbacks4_t. */
2050 static struct svn_wc_diff_callbacks4_t diff_callbacks3_wrapper = {
2051   wrap_4to3_file_opened,
2052   wrap_4to3_file_changed,
2053   wrap_4to3_file_added,
2054   wrap_4to3_file_deleted,
2055   wrap_4to3_dir_deleted,
2056   wrap_4to3_dir_opened,
2057   wrap_4to3_dir_added,
2058   wrap_4to3_dir_props_changed,
2059   wrap_4to3_dir_closed
2060 };
2061
2062
2063 svn_error_t *
2064 svn_wc_get_diff_editor6(const svn_delta_editor_t **editor,
2065                         void **edit_baton,
2066                         svn_wc_context_t *wc_ctx,
2067                         const char *anchor_abspath,
2068                         const char *target,
2069                         svn_depth_t depth,
2070                         svn_boolean_t ignore_ancestry,
2071                         svn_boolean_t show_copies_as_adds,
2072                         svn_boolean_t use_git_diff_format,
2073                         svn_boolean_t use_text_base,
2074                         svn_boolean_t reverse_order,
2075                         svn_boolean_t server_performs_filtering,
2076                         const apr_array_header_t *changelist_filter,
2077                         const svn_wc_diff_callbacks4_t *callbacks,
2078                         void *callback_baton,
2079                         svn_cancel_func_t cancel_func,
2080                         void *cancel_baton,
2081                         apr_pool_t *result_pool,
2082                         apr_pool_t *scratch_pool)
2083 {
2084   const svn_diff_tree_processor_t *diff_processor;
2085
2086   /* --git implies --show-copies-as-adds */
2087   if (use_git_diff_format)
2088     show_copies_as_adds = TRUE;
2089
2090   /* --show-copies-as-adds implies --notice-ancestry */
2091   if (show_copies_as_adds)
2092     ignore_ancestry = FALSE;
2093
2094   SVN_ERR(svn_wc__wrap_diff_callbacks(&diff_processor,
2095                                       callbacks, callback_baton, TRUE,
2096                                       result_pool, scratch_pool));
2097
2098   if (reverse_order)
2099     diff_processor = svn_diff__tree_processor_reverse_create(diff_processor, result_pool);
2100
2101   if (! show_copies_as_adds)
2102     diff_processor = svn_diff__tree_processor_copy_as_changed_create(
2103                               diff_processor, result_pool);
2104
2105   return svn_error_trace(
2106     svn_wc__get_diff_editor(editor, edit_baton,
2107                             wc_ctx,
2108                             anchor_abspath, target,
2109                             depth,
2110                             ignore_ancestry, use_text_base,
2111                             reverse_order, server_performs_filtering,
2112                             changelist_filter,
2113                             diff_processor,
2114                             cancel_func, cancel_baton,
2115                             result_pool, scratch_pool));
2116 }
2117
2118
2119 svn_error_t *
2120 svn_wc_get_diff_editor5(svn_wc_adm_access_t *anchor,
2121                         const char *target,
2122                         const svn_wc_diff_callbacks3_t *callbacks,
2123                         void *callback_baton,
2124                         svn_depth_t depth,
2125                         svn_boolean_t ignore_ancestry,
2126                         svn_boolean_t use_text_base,
2127                         svn_boolean_t reverse_order,
2128                         svn_cancel_func_t cancel_func,
2129                         void *cancel_baton,
2130                         const apr_array_header_t *changelist_filter,
2131                         const svn_delta_editor_t **editor,
2132                         void **edit_baton,
2133                         apr_pool_t *pool)
2134 {
2135   struct diff_callbacks3_wrapper_baton *b = apr_palloc(pool, sizeof(*b));
2136   svn_wc_context_t *wc_ctx;
2137   svn_wc__db_t *db = svn_wc__adm_get_db(anchor);
2138
2139   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, db, pool));
2140
2141   b->callbacks3 = callbacks;
2142   b->baton = callback_baton;
2143   b->db = db;
2144   b->anchor = svn_wc_adm_access_path(anchor);
2145   b->anchor_abspath = svn_wc__adm_access_abspath(anchor);
2146
2147   SVN_ERR(svn_wc_get_diff_editor6(editor,
2148                                    edit_baton,
2149                                    wc_ctx,
2150                                    b->anchor_abspath,
2151                                    target,
2152                                    depth,
2153                                    ignore_ancestry,
2154                                    FALSE,
2155                                    FALSE,
2156                                    use_text_base,
2157                                    reverse_order,
2158                                    FALSE,
2159                                    changelist_filter,
2160                                    &diff_callbacks3_wrapper,
2161                                    b,
2162                                    cancel_func,
2163                                    cancel_baton,
2164                                    pool,
2165                                    pool));
2166
2167   /* Can't destroy wc_ctx. It is used by the diff editor */
2168
2169    return SVN_NO_ERROR;
2170 }
2171
2172 svn_error_t *
2173 svn_wc_get_diff_editor4(svn_wc_adm_access_t *anchor,
2174                         const char *target,
2175                         const svn_wc_diff_callbacks2_t *callbacks,
2176                         void *callback_baton,
2177                         svn_depth_t depth,
2178                         svn_boolean_t ignore_ancestry,
2179                         svn_boolean_t use_text_base,
2180                         svn_boolean_t reverse_order,
2181                         svn_cancel_func_t cancel_func,
2182                         void *cancel_baton,
2183                         const apr_array_header_t *changelist_filter,
2184                         const svn_delta_editor_t **editor,
2185                         void **edit_baton,
2186                         apr_pool_t *pool)
2187 {
2188   struct diff_callbacks2_wrapper_baton *b = apr_palloc(pool, sizeof(*b));
2189   b->callbacks2 = callbacks;
2190   b->baton = callback_baton;
2191   return svn_wc_get_diff_editor5(anchor,
2192                                  target,
2193                                  &diff_callbacks2_wrapper,
2194                                  b,
2195                                  depth,
2196                                  ignore_ancestry,
2197                                  use_text_base,
2198                                  reverse_order,
2199                                  cancel_func,
2200                                  cancel_baton,
2201                                  changelist_filter,
2202                                  editor,
2203                                  edit_baton,
2204                                  pool);
2205 }
2206
2207 svn_error_t *
2208 svn_wc_get_diff_editor3(svn_wc_adm_access_t *anchor,
2209                         const char *target,
2210                         const svn_wc_diff_callbacks2_t *callbacks,
2211                         void *callback_baton,
2212                         svn_boolean_t recurse,
2213                         svn_boolean_t ignore_ancestry,
2214                         svn_boolean_t use_text_base,
2215                         svn_boolean_t reverse_order,
2216                         svn_cancel_func_t cancel_func,
2217                         void *cancel_baton,
2218                         const svn_delta_editor_t **editor,
2219                         void **edit_baton,
2220                         apr_pool_t *pool)
2221 {
2222   return svn_wc_get_diff_editor4(anchor,
2223                                  target,
2224                                  callbacks,
2225                                  callback_baton,
2226                                  SVN_DEPTH_INFINITY_OR_FILES(recurse),
2227                                  ignore_ancestry,
2228                                  use_text_base,
2229                                  reverse_order,
2230                                  cancel_func,
2231                                  cancel_baton,
2232                                  NULL,
2233                                  editor,
2234                                  edit_baton,
2235                                  pool);
2236 }
2237
2238 svn_error_t *
2239 svn_wc_get_diff_editor2(svn_wc_adm_access_t *anchor,
2240                         const char *target,
2241                         const svn_wc_diff_callbacks_t *callbacks,
2242                         void *callback_baton,
2243                         svn_boolean_t recurse,
2244                         svn_boolean_t ignore_ancestry,
2245                         svn_boolean_t use_text_base,
2246                         svn_boolean_t reverse_order,
2247                         svn_cancel_func_t cancel_func,
2248                         void *cancel_baton,
2249                         const svn_delta_editor_t **editor,
2250                         void **edit_baton,
2251                         apr_pool_t *pool)
2252 {
2253   struct diff_callbacks_wrapper_baton *b = apr_palloc(pool, sizeof(*b));
2254   b->callbacks = callbacks;
2255   b->baton = callback_baton;
2256   return svn_wc_get_diff_editor5(anchor, target, &diff_callbacks_wrapper, b,
2257                                  SVN_DEPTH_INFINITY_OR_FILES(recurse),
2258                                  ignore_ancestry, use_text_base,
2259                                  reverse_order, cancel_func, cancel_baton,
2260                                  NULL, editor, edit_baton, pool);
2261 }
2262
2263 svn_error_t *
2264 svn_wc_get_diff_editor(svn_wc_adm_access_t *anchor,
2265                        const char *target,
2266                        const svn_wc_diff_callbacks_t *callbacks,
2267                        void *callback_baton,
2268                        svn_boolean_t recurse,
2269                        svn_boolean_t use_text_base,
2270                        svn_boolean_t reverse_order,
2271                        svn_cancel_func_t cancel_func,
2272                        void *cancel_baton,
2273                        const svn_delta_editor_t **editor,
2274                        void **edit_baton,
2275                        apr_pool_t *pool)
2276 {
2277   return svn_wc_get_diff_editor2(anchor, target, callbacks, callback_baton,
2278                                  recurse, FALSE, use_text_base, reverse_order,
2279                                  cancel_func, cancel_baton,
2280                                  editor, edit_baton, pool);
2281 }
2282
2283 svn_error_t *
2284 svn_wc_diff5(svn_wc_adm_access_t *anchor,
2285              const char *target,
2286              const svn_wc_diff_callbacks3_t *callbacks,
2287              void *callback_baton,
2288              svn_depth_t depth,
2289              svn_boolean_t ignore_ancestry,
2290              const apr_array_header_t *changelist_filter,
2291              apr_pool_t *pool)
2292 {
2293   struct diff_callbacks3_wrapper_baton *b = apr_palloc(pool, sizeof(*b));
2294   svn_wc_context_t *wc_ctx;
2295   svn_wc__db_t *db = svn_wc__adm_get_db(anchor);
2296
2297   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, db, pool));
2298
2299   b->callbacks3 = callbacks;
2300   b->baton = callback_baton;
2301   b->anchor = svn_wc_adm_access_path(anchor);
2302   b->anchor_abspath = svn_wc__adm_access_abspath(anchor);
2303
2304   SVN_ERR(svn_wc_diff6(wc_ctx,
2305                        svn_dirent_join(b->anchor_abspath, target, pool),
2306                        &diff_callbacks3_wrapper,
2307                        b,
2308                        depth,
2309                        ignore_ancestry,
2310                        FALSE,
2311                        FALSE,
2312                        changelist_filter,
2313                        NULL, NULL,
2314                        pool));
2315
2316   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
2317 }
2318
2319 svn_error_t *
2320 svn_wc_diff4(svn_wc_adm_access_t *anchor,
2321              const char *target,
2322              const svn_wc_diff_callbacks2_t *callbacks,
2323              void *callback_baton,
2324              svn_depth_t depth,
2325              svn_boolean_t ignore_ancestry,
2326              const apr_array_header_t *changelist_filter,
2327              apr_pool_t *pool)
2328 {
2329   struct diff_callbacks2_wrapper_baton *b = apr_palloc(pool, sizeof(*b));
2330   b->callbacks2 = callbacks;
2331   b->baton = callback_baton;
2332
2333   return svn_wc_diff5(anchor, target, &diff_callbacks2_wrapper, b,
2334                       depth, ignore_ancestry, changelist_filter, pool);
2335 }
2336
2337 svn_error_t *
2338 svn_wc_diff3(svn_wc_adm_access_t *anchor,
2339              const char *target,
2340              const svn_wc_diff_callbacks2_t *callbacks,
2341              void *callback_baton,
2342              svn_boolean_t recurse,
2343              svn_boolean_t ignore_ancestry,
2344              apr_pool_t *pool)
2345 {
2346   return svn_wc_diff4(anchor, target, callbacks, callback_baton,
2347                       SVN_DEPTH_INFINITY_OR_FILES(recurse), ignore_ancestry,
2348                       NULL, pool);
2349 }
2350
2351 svn_error_t *
2352 svn_wc_diff2(svn_wc_adm_access_t *anchor,
2353              const char *target,
2354              const svn_wc_diff_callbacks_t *callbacks,
2355              void *callback_baton,
2356              svn_boolean_t recurse,
2357              svn_boolean_t ignore_ancestry,
2358              apr_pool_t *pool)
2359 {
2360   struct diff_callbacks_wrapper_baton *b = apr_pcalloc(pool, sizeof(*b));
2361   b->callbacks = callbacks;
2362   b->baton = callback_baton;
2363   return svn_wc_diff5(anchor, target, &diff_callbacks_wrapper, b,
2364                       SVN_DEPTH_INFINITY_OR_FILES(recurse), ignore_ancestry,
2365                       NULL, pool);
2366 }
2367
2368 svn_error_t *
2369 svn_wc_diff(svn_wc_adm_access_t *anchor,
2370             const char *target,
2371             const svn_wc_diff_callbacks_t *callbacks,
2372             void *callback_baton,
2373             svn_boolean_t recurse,
2374             apr_pool_t *pool)
2375 {
2376   return svn_wc_diff2(anchor, target, callbacks, callback_baton,
2377                       recurse, FALSE, pool);
2378 }
2379
2380 /*** From entries.c ***/
2381 svn_error_t *
2382 svn_wc_walk_entries2(const char *path,
2383                      svn_wc_adm_access_t *adm_access,
2384                      const svn_wc_entry_callbacks_t *walk_callbacks,
2385                      void *walk_baton,
2386                      svn_boolean_t show_hidden,
2387                      svn_cancel_func_t cancel_func,
2388                      void *cancel_baton,
2389                      apr_pool_t *pool)
2390 {
2391   svn_wc_entry_callbacks2_t walk_cb2 = { 0 };
2392   walk_cb2.found_entry = walk_callbacks->found_entry;
2393   walk_cb2.handle_error = svn_wc__walker_default_error_handler;
2394   return svn_wc_walk_entries3(path, adm_access,
2395                               &walk_cb2, walk_baton, svn_depth_infinity,
2396                               show_hidden, cancel_func, cancel_baton, pool);
2397 }
2398
2399 svn_error_t *
2400 svn_wc_walk_entries(const char *path,
2401                     svn_wc_adm_access_t *adm_access,
2402                     const svn_wc_entry_callbacks_t *walk_callbacks,
2403                     void *walk_baton,
2404                     svn_boolean_t show_hidden,
2405                     apr_pool_t *pool)
2406 {
2407   return svn_wc_walk_entries2(path, adm_access, walk_callbacks,
2408                               walk_baton, show_hidden, NULL, NULL,
2409                               pool);
2410 }
2411
2412 svn_error_t *
2413 svn_wc_mark_missing_deleted(const char *path,
2414                             svn_wc_adm_access_t *parent,
2415                             apr_pool_t *pool)
2416 {
2417   /* With a single DB a node will never be missing */
2418   return svn_error_createf(SVN_ERR_WC_PATH_FOUND, NULL,
2419                            _("Unexpectedly found '%s': "
2420                              "path is marked 'missing'"),
2421                            svn_dirent_local_style(path, pool));
2422 }
2423
2424
2425 /*** From props.c ***/
2426 svn_error_t *
2427 svn_wc_parse_externals_description2(apr_array_header_t **externals_p,
2428                                     const char *parent_directory,
2429                                     const char *desc,
2430                                     apr_pool_t *pool)
2431 {
2432   apr_array_header_t *list;
2433   apr_pool_t *subpool = svn_pool_create(pool);
2434
2435   SVN_ERR(svn_wc_parse_externals_description3(externals_p ? &list : NULL,
2436                                               parent_directory, desc,
2437                                               TRUE, subpool));
2438
2439   if (externals_p)
2440     {
2441       int i;
2442
2443       *externals_p = apr_array_make(pool, list->nelts,
2444                                     sizeof(svn_wc_external_item_t *));
2445       for (i = 0; i < list->nelts; i++)
2446         {
2447           svn_wc_external_item2_t *item2 = APR_ARRAY_IDX(list, i,
2448                                              svn_wc_external_item2_t *);
2449           svn_wc_external_item_t *item = apr_palloc(pool, sizeof (*item));
2450
2451           if (item2->target_dir)
2452             item->target_dir = apr_pstrdup(pool, item2->target_dir);
2453           if (item2->url)
2454             item->url = apr_pstrdup(pool, item2->url);
2455           item->revision = item2->revision;
2456
2457           APR_ARRAY_PUSH(*externals_p, svn_wc_external_item_t *) = item;
2458         }
2459     }
2460
2461   svn_pool_destroy(subpool);
2462
2463   return SVN_NO_ERROR;
2464 }
2465
2466
2467 svn_error_t *
2468 svn_wc_parse_externals_description(apr_hash_t **externals_p,
2469                                    const char *parent_directory,
2470                                    const char *desc,
2471                                    apr_pool_t *pool)
2472 {
2473   apr_array_header_t *list;
2474
2475   SVN_ERR(svn_wc_parse_externals_description2(externals_p ? &list : NULL,
2476                                               parent_directory, desc, pool));
2477
2478   /* Store all of the items into the hash if that was requested. */
2479   if (externals_p)
2480     {
2481       int i;
2482
2483       *externals_p = apr_hash_make(pool);
2484       for (i = 0; i < list->nelts; i++)
2485         {
2486           svn_wc_external_item_t *item;
2487           item = APR_ARRAY_IDX(list, i, svn_wc_external_item_t *);
2488
2489           svn_hash_sets(*externals_p, item->target_dir, item);
2490         }
2491     }
2492   return SVN_NO_ERROR;
2493 }
2494
2495 svn_error_t *
2496 svn_wc_prop_set3(const char *name,
2497                  const svn_string_t *value,
2498                  const char *path,
2499                  svn_wc_adm_access_t *adm_access,
2500                  svn_boolean_t skip_checks,
2501                  svn_wc_notify_func2_t notify_func,
2502                  void *notify_baton,
2503                  apr_pool_t *pool)
2504 {
2505   svn_wc_context_t *wc_ctx;
2506   const char *local_abspath;
2507   svn_error_t *err;
2508
2509   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
2510   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
2511                                          svn_wc__adm_get_db(adm_access),
2512                                          pool));
2513
2514   err = svn_wc_prop_set4(wc_ctx, local_abspath,
2515                          name, value,
2516                          svn_depth_empty,
2517                          skip_checks, NULL /* changelist_filter */,
2518                          NULL, NULL /* cancellation */,
2519                          notify_func, notify_baton,
2520                          pool);
2521
2522   if (err && err->apr_err == SVN_ERR_WC_INVALID_SCHEDULE)
2523     svn_error_clear(err);
2524   else
2525     SVN_ERR(err);
2526
2527   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
2528 }
2529
2530 svn_error_t *
2531 svn_wc_prop_set2(const char *name,
2532                  const svn_string_t *value,
2533                  const char *path,
2534                  svn_wc_adm_access_t *adm_access,
2535                  svn_boolean_t skip_checks,
2536                  apr_pool_t *pool)
2537 {
2538   return svn_wc_prop_set3(name, value, path, adm_access, skip_checks,
2539                           NULL, NULL, pool);
2540 }
2541
2542 svn_error_t *
2543 svn_wc_prop_set(const char *name,
2544                 const svn_string_t *value,
2545                 const char *path,
2546                 svn_wc_adm_access_t *adm_access,
2547                 apr_pool_t *pool)
2548 {
2549   return svn_wc_prop_set2(name, value, path, adm_access, FALSE, pool);
2550 }
2551
2552 svn_error_t *
2553 svn_wc_prop_list(apr_hash_t **props,
2554                  const char *path,
2555                  svn_wc_adm_access_t *adm_access,
2556                  apr_pool_t *pool)
2557 {
2558   svn_wc_context_t *wc_ctx;
2559   const char *local_abspath;
2560   svn_error_t *err;
2561
2562   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
2563   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
2564                                          svn_wc__adm_get_db(adm_access), pool));
2565
2566   err = svn_wc_prop_list2(props, wc_ctx, local_abspath, pool, pool);
2567   if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
2568     {
2569       *props = apr_hash_make(pool);
2570       svn_error_clear(err);
2571       err = NULL;
2572     }
2573
2574   return svn_error_compose_create(err, svn_wc_context_destroy(wc_ctx));
2575 }
2576
2577 svn_error_t *
2578 svn_wc_prop_get(const svn_string_t **value,
2579                 const char *name,
2580                 const char *path,
2581                 svn_wc_adm_access_t *adm_access,
2582                 apr_pool_t *pool)
2583 {
2584
2585   svn_wc_context_t *wc_ctx;
2586   const char *local_abspath;
2587   svn_error_t *err;
2588
2589   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
2590   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
2591                                          svn_wc__adm_get_db(adm_access), pool));
2592
2593   err = svn_wc_prop_get2(value, wc_ctx, local_abspath, name, pool, pool);
2594
2595   if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
2596     {
2597       *value = NULL;
2598       svn_error_clear(err);
2599       err = NULL;
2600     }
2601
2602   return svn_error_compose_create(err, svn_wc_context_destroy(wc_ctx));
2603 }
2604
2605 /* baton for conflict_func_1to2_wrapper */
2606 struct conflict_func_1to2_baton
2607 {
2608   svn_wc_conflict_resolver_func_t inner_func;
2609   void *inner_baton;
2610 };
2611
2612
2613 /* Implements svn_wc_conflict_resolver_func2_t */
2614 static svn_error_t *
2615 conflict_func_1to2_wrapper(svn_wc_conflict_result_t **result,
2616                            const svn_wc_conflict_description2_t *conflict,
2617                            void *baton,
2618                            apr_pool_t *result_pool,
2619                            apr_pool_t *scratch_pool)
2620 {
2621   struct conflict_func_1to2_baton *btn = baton;
2622   svn_wc_conflict_description_t *cd = svn_wc__cd2_to_cd(conflict,
2623                                                         scratch_pool);
2624
2625   return svn_error_trace(btn->inner_func(result, cd, btn->inner_baton,
2626                                          result_pool));
2627 }
2628
2629 svn_error_t *
2630 svn_wc_merge_props2(svn_wc_notify_state_t *state,
2631                     const char *path,
2632                     svn_wc_adm_access_t *adm_access,
2633                     apr_hash_t *baseprops,
2634                     const apr_array_header_t *propchanges,
2635                     svn_boolean_t base_merge,
2636                     svn_boolean_t dry_run,
2637                     svn_wc_conflict_resolver_func_t conflict_func,
2638                     void *conflict_baton,
2639                     apr_pool_t *scratch_pool)
2640 {
2641   const char *local_abspath;
2642   svn_error_t *err;
2643   svn_wc_context_t *wc_ctx;
2644   struct conflict_func_1to2_baton conflict_wrapper;
2645
2646   if (base_merge && !dry_run)
2647     return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
2648                             U_("base_merge=TRUE is no longer supported; "
2649                                "see notes/api-errata/1.7/wc006.txt"));
2650
2651   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, scratch_pool));
2652
2653   conflict_wrapper.inner_func = conflict_func;
2654   conflict_wrapper.inner_baton = conflict_baton;
2655
2656   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL,
2657                                          svn_wc__adm_get_db(adm_access),
2658                                          scratch_pool));
2659
2660   err = svn_wc_merge_props3(state,
2661                             wc_ctx,
2662                             local_abspath,
2663                             NULL /* left_version */,
2664                             NULL /* right_version */,
2665                             baseprops,
2666                             propchanges,
2667                             dry_run,
2668                             conflict_func ? conflict_func_1to2_wrapper
2669                                           : NULL,
2670                             &conflict_wrapper,
2671                             NULL, NULL,
2672                             scratch_pool);
2673
2674   if (err)
2675     switch(err->apr_err)
2676       {
2677         case SVN_ERR_WC_PATH_NOT_FOUND:
2678         case SVN_ERR_WC_PATH_UNEXPECTED_STATUS:
2679           err->apr_err = SVN_ERR_UNVERSIONED_RESOURCE;
2680           break;
2681       }
2682   return svn_error_trace(
2683             svn_error_compose_create(err,
2684                                      svn_wc_context_destroy(wc_ctx)));
2685 }
2686
2687 svn_error_t *
2688 svn_wc_merge_props(svn_wc_notify_state_t *state,
2689                    const char *path,
2690                    svn_wc_adm_access_t *adm_access,
2691                    apr_hash_t *baseprops,
2692                    const apr_array_header_t *propchanges,
2693                    svn_boolean_t base_merge,
2694                    svn_boolean_t dry_run,
2695                    apr_pool_t *pool)
2696 {
2697   return svn_wc_merge_props2(state, path, adm_access, baseprops, propchanges,
2698                              base_merge, dry_run, NULL, NULL, pool);
2699 }
2700
2701
2702 svn_error_t *
2703 svn_wc_merge_prop_diffs(svn_wc_notify_state_t *state,
2704                         const char *path,
2705                         svn_wc_adm_access_t *adm_access,
2706                         const apr_array_header_t *propchanges,
2707                         svn_boolean_t base_merge,
2708                         svn_boolean_t dry_run,
2709                         apr_pool_t *pool)
2710 {
2711   /* NOTE: Here, we use implementation knowledge.  The public
2712      svn_wc_merge_props2 doesn't allow NULL as baseprops argument, but we know
2713      that it works. */
2714   return svn_wc_merge_props2(state, path, adm_access, NULL, propchanges,
2715                              base_merge, dry_run, NULL, NULL, pool);
2716 }
2717
2718 svn_error_t *
2719 svn_wc_get_prop_diffs(apr_array_header_t **propchanges,
2720                       apr_hash_t **original_props,
2721                       const char *path,
2722                       svn_wc_adm_access_t *adm_access,
2723                       apr_pool_t *pool)
2724 {
2725   svn_wc_context_t *wc_ctx;
2726   const char *local_abspath;
2727
2728   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
2729   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
2730                                          svn_wc__adm_get_db(adm_access), pool));
2731
2732   SVN_ERR(svn_wc_get_prop_diffs2(propchanges, original_props, wc_ctx,
2733                                  local_abspath, pool, pool));
2734
2735   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
2736 }
2737
2738
2739 svn_error_t *
2740 svn_wc_props_modified_p(svn_boolean_t *modified_p,
2741                         const char *path,
2742                         svn_wc_adm_access_t *adm_access,
2743                         apr_pool_t *pool)
2744 {
2745   svn_wc_context_t *wc_ctx;
2746   const char *local_abspath;
2747   svn_error_t *err;
2748
2749   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
2750   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
2751                                          svn_wc__adm_get_db(adm_access), pool));
2752
2753   err = svn_wc_props_modified_p2(modified_p,
2754                                  wc_ctx,
2755                                  local_abspath,
2756                                  pool);
2757
2758   if (err)
2759     {
2760       if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
2761         return svn_error_trace(err);
2762
2763       svn_error_clear(err);
2764       *modified_p = FALSE;
2765     }
2766
2767   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
2768 }
2769
2770
2771 svn_error_t *
2772 svn_wc__status2_from_3(svn_wc_status2_t **status,
2773                        const svn_wc_status3_t *old_status,
2774                        svn_wc_context_t *wc_ctx,
2775                        const char *local_abspath,
2776                        apr_pool_t *result_pool,
2777                        apr_pool_t *scratch_pool)
2778 {
2779   const svn_wc_entry_t *entry = NULL;
2780
2781   if (old_status == NULL)
2782     {
2783       *status = NULL;
2784       return SVN_NO_ERROR;
2785     }
2786
2787   *status = apr_pcalloc(result_pool, sizeof(**status));
2788
2789   if (old_status->versioned)
2790     {
2791       svn_error_t *err;
2792       err= svn_wc__get_entry(&entry, wc_ctx->db, local_abspath, FALSE,
2793                              svn_node_unknown, result_pool, scratch_pool);
2794
2795       if (err && err->apr_err == SVN_ERR_NODE_UNEXPECTED_KIND)
2796         svn_error_clear(err);
2797       else
2798         SVN_ERR(err);
2799     }
2800
2801   (*status)->entry = entry;
2802   (*status)->copied = old_status->copied;
2803   (*status)->repos_lock = svn_lock_dup(old_status->repos_lock, result_pool);
2804
2805   if (old_status->repos_relpath)
2806     (*status)->url = svn_path_url_add_component2(old_status->repos_root_url,
2807                                                  old_status->repos_relpath,
2808                                                  result_pool);
2809   (*status)->ood_last_cmt_rev = old_status->ood_changed_rev;
2810   (*status)->ood_last_cmt_date = old_status->ood_changed_date;
2811   (*status)->ood_kind = old_status->ood_kind;
2812   (*status)->ood_last_cmt_author = old_status->ood_changed_author;
2813
2814   if (old_status->conflicted)
2815     {
2816       const svn_wc_conflict_description2_t *tree_conflict2;
2817       SVN_ERR(svn_wc__get_tree_conflict(&tree_conflict2, wc_ctx, local_abspath,
2818                                         scratch_pool, scratch_pool));
2819       (*status)->tree_conflict = svn_wc__cd2_to_cd(tree_conflict2, result_pool);
2820     }
2821
2822   (*status)->switched = old_status->switched;
2823
2824   (*status)->text_status = old_status->node_status;
2825   (*status)->prop_status = old_status->prop_status;
2826
2827   (*status)->repos_text_status = old_status->repos_node_status;
2828   (*status)->repos_prop_status = old_status->repos_prop_status;
2829
2830   /* Some values might be inherited from properties */
2831   if (old_status->node_status == svn_wc_status_modified
2832       || old_status->node_status == svn_wc_status_conflicted)
2833     (*status)->text_status = old_status->text_status;
2834
2835   /* (Currently a no-op, but just make sure it is ok) */
2836   if (old_status->repos_node_status == svn_wc_status_modified
2837       || old_status->repos_node_status == svn_wc_status_conflicted)
2838     (*status)->repos_text_status = old_status->repos_text_status;
2839
2840   if (old_status->node_status == svn_wc_status_added)
2841     (*status)->prop_status = svn_wc_status_none; /* No separate info */
2842
2843   /* Find pristine_text_status value */
2844   switch (old_status->text_status)
2845     {
2846       case svn_wc_status_none:
2847       case svn_wc_status_normal:
2848       case svn_wc_status_modified:
2849         (*status)->pristine_text_status = old_status->text_status;
2850         break;
2851       case svn_wc_status_conflicted:
2852       default:
2853         /* ### Fetch compare data, or fall back to the documented
2854                not retrieved behavior? */
2855         (*status)->pristine_text_status = svn_wc_status_none;
2856         break;
2857     }
2858
2859   /* Find pristine_prop_status value */
2860   switch (old_status->prop_status)
2861     {
2862       case svn_wc_status_none:
2863       case svn_wc_status_normal:
2864       case svn_wc_status_modified:
2865         if (old_status->node_status != svn_wc_status_added
2866             && old_status->node_status != svn_wc_status_deleted
2867             && old_status->node_status != svn_wc_status_replaced)
2868           {
2869             (*status)->pristine_prop_status = old_status->prop_status;
2870           }
2871         else
2872           (*status)->pristine_prop_status = svn_wc_status_none;
2873         break;
2874       case svn_wc_status_conflicted:
2875       default:
2876         /* ### Fetch compare data, or fall back to the documented
2877                not retrieved behavior? */
2878         (*status)->pristine_prop_status = svn_wc_status_none;
2879         break;
2880     }
2881
2882   if (old_status->versioned
2883       && old_status->conflicted
2884       && old_status->node_status != svn_wc_status_obstructed
2885       && (old_status->kind == svn_node_file
2886           || old_status->node_status != svn_wc_status_missing))
2887     {
2888       svn_boolean_t text_conflict_p, prop_conflict_p;
2889
2890       /* The entry says there was a conflict, but the user might have
2891          marked it as resolved by deleting the artifact files, so check
2892          for that. */
2893       SVN_ERR(svn_wc__internal_conflicted_p(&text_conflict_p,
2894                                             &prop_conflict_p,
2895                                             NULL,
2896                                             wc_ctx->db, local_abspath,
2897                                             scratch_pool));
2898
2899       if (text_conflict_p)
2900         (*status)->text_status = svn_wc_status_conflicted;
2901
2902       if (prop_conflict_p)
2903         (*status)->prop_status = svn_wc_status_conflicted;
2904     }
2905
2906   return SVN_NO_ERROR;
2907 }
2908
2909
2910
2911 /*** From status.c ***/
2912
2913 struct status4_wrapper_baton
2914 {
2915   svn_wc_status_func3_t old_func;
2916   void *old_baton;
2917   const char *anchor_abspath;
2918   const char *anchor_relpath;
2919   svn_wc_context_t *wc_ctx;
2920 };
2921
2922 /* */
2923 static svn_error_t *
2924 status4_wrapper_func(void *baton,
2925                      const char *local_abspath,
2926                      const svn_wc_status3_t *status,
2927                      apr_pool_t *scratch_pool)
2928 {
2929   struct status4_wrapper_baton *swb = baton;
2930   svn_wc_status2_t *dup;
2931   const char *path = local_abspath;
2932
2933   SVN_ERR(svn_wc__status2_from_3(&dup, status, swb->wc_ctx, local_abspath,
2934                                  scratch_pool, scratch_pool));
2935
2936   if (swb->anchor_abspath != NULL)
2937     {
2938       path = svn_dirent_join(
2939                 swb->anchor_relpath,
2940                 svn_dirent_skip_ancestor(swb->anchor_abspath, local_abspath),
2941                 scratch_pool);
2942     }
2943
2944   return (*swb->old_func)(swb->old_baton, path, dup, scratch_pool);
2945 }
2946
2947
2948 svn_error_t *
2949 svn_wc_get_status_editor5(const svn_delta_editor_t **editor,
2950                           void **edit_baton,
2951                           void **set_locks_baton,
2952                           svn_revnum_t *edit_revision,
2953                           svn_wc_context_t *wc_ctx,
2954                           const char *anchor_abspath,
2955                           const char *target_basename,
2956                           svn_depth_t depth,
2957                           svn_boolean_t get_all,
2958                           svn_boolean_t no_ignore,
2959                           svn_boolean_t depth_as_sticky,
2960                           svn_boolean_t server_performs_filtering,
2961                           const apr_array_header_t *ignore_patterns,
2962                           svn_wc_status_func4_t status_func,
2963                           void *status_baton,
2964                           svn_cancel_func_t cancel_func,
2965                           void *cancel_baton,
2966                           apr_pool_t *result_pool,
2967                           apr_pool_t *scratch_pool)
2968 {
2969   return svn_error_trace(
2970     svn_wc__get_status_editor(editor, edit_baton,
2971                               set_locks_baton,
2972                               edit_revision,
2973                               wc_ctx,
2974                               anchor_abspath,
2975                               target_basename,
2976                               depth, get_all,
2977                               TRUE, /* check_working_copy */
2978                               no_ignore, depth_as_sticky,
2979                               server_performs_filtering,
2980                               ignore_patterns,
2981                               status_func, status_baton,
2982                               cancel_func, cancel_baton,
2983                               result_pool,
2984                               scratch_pool));
2985 }
2986
2987
2988 svn_error_t *
2989 svn_wc_get_status_editor4(const svn_delta_editor_t **editor,
2990                           void **edit_baton,
2991                           void **set_locks_baton,
2992                           svn_revnum_t *edit_revision,
2993                           svn_wc_adm_access_t *anchor,
2994                           const char *target,
2995                           svn_depth_t depth,
2996                           svn_boolean_t get_all,
2997                           svn_boolean_t no_ignore,
2998                           const apr_array_header_t *ignore_patterns,
2999                           svn_wc_status_func3_t status_func,
3000                           void *status_baton,
3001                           svn_cancel_func_t cancel_func,
3002                           void *cancel_baton,
3003                           svn_wc_traversal_info_t *traversal_info,
3004                           apr_pool_t *pool)
3005 {
3006   struct status4_wrapper_baton *swb = apr_palloc(pool, sizeof(*swb));
3007   svn_wc__db_t *wc_db;
3008   svn_wc_context_t *wc_ctx;
3009   const char *anchor_abspath;
3010
3011   swb->old_func = status_func;
3012   swb->old_baton = status_baton;
3013
3014   wc_db = svn_wc__adm_get_db(anchor);
3015
3016   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
3017                                          wc_db, pool));
3018
3019   swb->wc_ctx = wc_ctx;
3020
3021   anchor_abspath = svn_wc__adm_access_abspath(anchor);
3022
3023   if (!svn_dirent_is_absolute(svn_wc_adm_access_path(anchor)))
3024     {
3025       swb->anchor_abspath = anchor_abspath;
3026       swb->anchor_relpath = svn_wc_adm_access_path(anchor);
3027     }
3028   else
3029     {
3030       swb->anchor_abspath = NULL;
3031       swb->anchor_relpath = NULL;
3032     }
3033
3034   /* Before subversion 1.7 status always handled depth as sticky. 1.7 made
3035      the output of svn status by default match the result of what would be
3036      updated by a similar svn update. (Following the documentation) */
3037
3038   SVN_ERR(svn_wc_get_status_editor5(editor, edit_baton, set_locks_baton,
3039                                     edit_revision, wc_ctx, anchor_abspath,
3040                                     target, depth, get_all,
3041                                     no_ignore,
3042                                     (depth != svn_depth_unknown) /*as_sticky*/,
3043                                     FALSE /* server_performs_filtering */,
3044                                     ignore_patterns,
3045                                     status4_wrapper_func, swb,
3046                                     cancel_func, cancel_baton,
3047                                     pool, pool));
3048
3049   if (traversal_info)
3050     {
3051       const char *local_path = svn_wc_adm_access_path(anchor);
3052       const char *local_abspath = anchor_abspath;
3053       if (*target)
3054         {
3055           local_path = svn_dirent_join(local_path, target, pool);
3056           local_abspath = svn_dirent_join(local_abspath, target, pool);
3057         }
3058
3059       SVN_ERR(gather_traversal_info(wc_ctx, local_abspath, local_path, depth,
3060                                     traversal_info, TRUE, TRUE,
3061                                     pool));
3062     }
3063
3064   /* We can't destroy wc_ctx here, because the editor needs it while it's
3065      driven. */
3066   return SVN_NO_ERROR;
3067 }
3068
3069 struct status_editor3_compat_baton
3070 {
3071   svn_wc_status_func2_t old_func;
3072   void *old_baton;
3073 };
3074
3075 /* */
3076 static svn_error_t *
3077 status_editor3_compat_func(void *baton,
3078                            const char *path,
3079                            svn_wc_status2_t *status,
3080                            apr_pool_t *pool)
3081 {
3082   struct status_editor3_compat_baton *secb = baton;
3083
3084   secb->old_func(secb->old_baton, path, status);
3085   return SVN_NO_ERROR;
3086 }
3087
3088 svn_error_t *
3089 svn_wc_get_status_editor3(const svn_delta_editor_t **editor,
3090                           void **edit_baton,
3091                           void **set_locks_baton,
3092                           svn_revnum_t *edit_revision,
3093                           svn_wc_adm_access_t *anchor,
3094                           const char *target,
3095                           svn_depth_t depth,
3096                           svn_boolean_t get_all,
3097                           svn_boolean_t no_ignore,
3098                           const apr_array_header_t *ignore_patterns,
3099                           svn_wc_status_func2_t status_func,
3100                           void *status_baton,
3101                           svn_cancel_func_t cancel_func,
3102                           void *cancel_baton,
3103                           svn_wc_traversal_info_t *traversal_info,
3104                           apr_pool_t *pool)
3105 {
3106   /* This baton must live beyond this function. Alloc on heap.  */
3107   struct status_editor3_compat_baton *secb = apr_palloc(pool, sizeof(*secb));
3108
3109   secb->old_func = status_func;
3110   secb->old_baton = status_baton;
3111
3112   return svn_wc_get_status_editor4(editor, edit_baton, set_locks_baton,
3113                                    edit_revision, anchor, target, depth,
3114                                    get_all, no_ignore, ignore_patterns,
3115                                    status_editor3_compat_func, secb,
3116                                    cancel_func, cancel_baton, traversal_info,
3117                                    pool);
3118 }
3119
3120 svn_error_t *
3121 svn_wc_get_status_editor2(const svn_delta_editor_t **editor,
3122                           void **edit_baton,
3123                           void **set_locks_baton,
3124                           svn_revnum_t *edit_revision,
3125                           svn_wc_adm_access_t *anchor,
3126                           const char *target,
3127                           apr_hash_t *config,
3128                           svn_boolean_t recurse,
3129                           svn_boolean_t get_all,
3130                           svn_boolean_t no_ignore,
3131                           svn_wc_status_func2_t status_func,
3132                           void *status_baton,
3133                           svn_cancel_func_t cancel_func,
3134                           void *cancel_baton,
3135                           svn_wc_traversal_info_t *traversal_info,
3136                           apr_pool_t *pool)
3137 {
3138   apr_array_header_t *ignores;
3139
3140   SVN_ERR(svn_wc_get_default_ignores(&ignores, config, pool));
3141   return svn_wc_get_status_editor3(editor,
3142                                    edit_baton,
3143                                    set_locks_baton,
3144                                    edit_revision,
3145                                    anchor,
3146                                    target,
3147                                    SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse),
3148                                    get_all,
3149                                    no_ignore,
3150                                    ignores,
3151                                    status_func,
3152                                    status_baton,
3153                                    cancel_func,
3154                                    cancel_baton,
3155                                    traversal_info,
3156                                    pool);
3157 }
3158
3159
3160 /* Helpers for deprecated svn_wc_status_editor(), of type
3161    svn_wc_status_func2_t. */
3162 struct old_status_func_cb_baton
3163 {
3164   svn_wc_status_func_t original_func;
3165   void *original_baton;
3166 };
3167
3168 /* */
3169 static void old_status_func_cb(void *baton,
3170                                const char *path,
3171                                svn_wc_status2_t *status)
3172 {
3173   struct old_status_func_cb_baton *b = baton;
3174   svn_wc_status_t *stat = (svn_wc_status_t *) status;
3175
3176   b->original_func(b->original_baton, path, stat);
3177 }
3178
3179 svn_error_t *
3180 svn_wc_get_status_editor(const svn_delta_editor_t **editor,
3181                          void **edit_baton,
3182                          svn_revnum_t *edit_revision,
3183                          svn_wc_adm_access_t *anchor,
3184                          const char *target,
3185                          apr_hash_t *config,
3186                          svn_boolean_t recurse,
3187                          svn_boolean_t get_all,
3188                          svn_boolean_t no_ignore,
3189                          svn_wc_status_func_t status_func,
3190                          void *status_baton,
3191                          svn_cancel_func_t cancel_func,
3192                          void *cancel_baton,
3193                          svn_wc_traversal_info_t *traversal_info,
3194                          apr_pool_t *pool)
3195 {
3196   struct old_status_func_cb_baton *b = apr_pcalloc(pool, sizeof(*b));
3197   apr_array_header_t *ignores;
3198   b->original_func = status_func;
3199   b->original_baton = status_baton;
3200   SVN_ERR(svn_wc_get_default_ignores(&ignores, config, pool));
3201   return svn_wc_get_status_editor3(editor, edit_baton, NULL, edit_revision,
3202                                    anchor, target,
3203                                    SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse),
3204                                    get_all, no_ignore, ignores,
3205                                    old_status_func_cb, b,
3206                                    cancel_func, cancel_baton,
3207                                    traversal_info, pool);
3208 }
3209
3210 svn_error_t *
3211 svn_wc_status(svn_wc_status_t **status,
3212               const char *path,
3213               svn_wc_adm_access_t *adm_access,
3214               apr_pool_t *pool)
3215 {
3216   svn_wc_status2_t *stat2;
3217
3218   SVN_ERR(svn_wc_status2(&stat2, path, adm_access, pool));
3219   *status = (svn_wc_status_t *) stat2;
3220   return SVN_NO_ERROR;
3221 }
3222
3223
3224 static svn_wc_conflict_description_t *
3225 conflict_description_dup(const svn_wc_conflict_description_t *conflict,
3226                          apr_pool_t *pool)
3227 {
3228   svn_wc_conflict_description_t *new_conflict;
3229
3230   new_conflict = apr_pcalloc(pool, sizeof(*new_conflict));
3231
3232   /* Shallow copy all members. */
3233   *new_conflict = *conflict;
3234
3235   if (conflict->path)
3236     new_conflict->path = apr_pstrdup(pool, conflict->path);
3237   if (conflict->property_name)
3238     new_conflict->property_name = apr_pstrdup(pool, conflict->property_name);
3239   if (conflict->mime_type)
3240     new_conflict->mime_type = apr_pstrdup(pool, conflict->mime_type);
3241   /* NOTE: We cannot make a deep copy of adm_access. */
3242   if (conflict->base_file)
3243     new_conflict->base_file = apr_pstrdup(pool, conflict->base_file);
3244   if (conflict->their_file)
3245     new_conflict->their_file = apr_pstrdup(pool, conflict->their_file);
3246   if (conflict->my_file)
3247     new_conflict->my_file = apr_pstrdup(pool, conflict->my_file);
3248   if (conflict->merged_file)
3249     new_conflict->merged_file = apr_pstrdup(pool, conflict->merged_file);
3250   if (conflict->src_left_version)
3251     new_conflict->src_left_version =
3252       svn_wc_conflict_version_dup(conflict->src_left_version, pool);
3253   if (conflict->src_right_version)
3254     new_conflict->src_right_version =
3255       svn_wc_conflict_version_dup(conflict->src_right_version, pool);
3256
3257   return new_conflict;
3258 }
3259
3260
3261 svn_wc_status2_t *
3262 svn_wc_dup_status2(const svn_wc_status2_t *orig_stat,
3263                    apr_pool_t *pool)
3264 {
3265   svn_wc_status2_t *new_stat = apr_palloc(pool, sizeof(*new_stat));
3266
3267   /* Shallow copy all members. */
3268   *new_stat = *orig_stat;
3269
3270   /* Now go back and dup the deep items into this pool. */
3271   if (orig_stat->entry)
3272     new_stat->entry = svn_wc_entry_dup(orig_stat->entry, pool);
3273
3274   if (orig_stat->repos_lock)
3275     new_stat->repos_lock = svn_lock_dup(orig_stat->repos_lock, pool);
3276
3277   if (orig_stat->url)
3278     new_stat->url = apr_pstrdup(pool, orig_stat->url);
3279
3280   if (orig_stat->ood_last_cmt_author)
3281     new_stat->ood_last_cmt_author
3282       = apr_pstrdup(pool, orig_stat->ood_last_cmt_author);
3283
3284   if (orig_stat->tree_conflict)
3285     new_stat->tree_conflict
3286       = conflict_description_dup(orig_stat->tree_conflict, pool);
3287
3288   /* Return the new hotness. */
3289   return new_stat;
3290 }
3291
3292 svn_wc_status_t *
3293 svn_wc_dup_status(const svn_wc_status_t *orig_stat,
3294                   apr_pool_t *pool)
3295 {
3296   svn_wc_status_t *new_stat = apr_palloc(pool, sizeof(*new_stat));
3297
3298   /* Shallow copy all members. */
3299   *new_stat = *orig_stat;
3300
3301   /* Now go back and dup the deep item into this pool. */
3302   if (orig_stat->entry)
3303     new_stat->entry = svn_wc_entry_dup(orig_stat->entry, pool);
3304
3305   /* Return the new hotness. */
3306   return new_stat;
3307 }
3308
3309 svn_error_t *
3310 svn_wc_get_ignores(apr_array_header_t **patterns,
3311                    apr_hash_t *config,
3312                    svn_wc_adm_access_t *adm_access,
3313                    apr_pool_t *pool)
3314 {
3315   svn_wc_context_t *wc_ctx;
3316   const char *local_abspath;
3317
3318   SVN_ERR(svn_dirent_get_absolute(&local_abspath,
3319                                   svn_wc_adm_access_path(adm_access), pool));
3320
3321   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
3322                                          svn_wc__adm_get_db(adm_access),
3323                                          pool));
3324
3325   SVN_ERR(svn_wc_get_ignores2(patterns, wc_ctx, local_abspath, config, pool,
3326                               pool));
3327
3328   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
3329 }
3330
3331 svn_error_t *
3332 svn_wc_status2(svn_wc_status2_t **status,
3333                const char *path,
3334                svn_wc_adm_access_t *adm_access,
3335                apr_pool_t *pool)
3336 {
3337   const char *local_abspath;
3338   svn_wc_context_t *wc_ctx;
3339   svn_wc_status3_t *stat3;
3340
3341   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
3342   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
3343                                          svn_wc__adm_get_db(adm_access),
3344                                          pool));
3345
3346   SVN_ERR(svn_wc_status3(&stat3, wc_ctx, local_abspath, pool, pool));
3347   SVN_ERR(svn_wc__status2_from_3(status, stat3, wc_ctx, local_abspath,
3348                                  pool, pool));
3349
3350   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
3351 }
3352
3353
3354 /*** From update_editor.c ***/
3355
3356 svn_error_t *
3357 svn_wc_add_repos_file3(const char *dst_path,
3358                        svn_wc_adm_access_t *adm_access,
3359                        svn_stream_t *new_base_contents,
3360                        svn_stream_t *new_contents,
3361                        apr_hash_t *new_base_props,
3362                        apr_hash_t *new_props,
3363                        const char *copyfrom_url,
3364                        svn_revnum_t copyfrom_rev,
3365                        svn_cancel_func_t cancel_func,
3366                        void *cancel_baton,
3367                        svn_wc_notify_func2_t notify_func,
3368                        void *notify_baton,
3369                        apr_pool_t *pool)
3370 {
3371   const char *local_abspath;
3372   svn_wc_context_t *wc_ctx;
3373
3374   SVN_ERR(svn_dirent_get_absolute(&local_abspath, dst_path, pool));
3375   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
3376                                          svn_wc__adm_get_db(adm_access),
3377                                          pool));
3378
3379   SVN_ERR(svn_wc_add_repos_file4(wc_ctx,
3380                                  local_abspath,
3381                                  new_base_contents,
3382                                  new_contents,
3383                                  new_base_props,
3384                                  new_props,
3385                                  copyfrom_url,
3386                                  copyfrom_rev,
3387                                  cancel_func, cancel_baton,
3388                                  pool));
3389
3390   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
3391 }
3392
3393 svn_error_t *
3394 svn_wc_add_repos_file2(const char *dst_path,
3395                        svn_wc_adm_access_t *adm_access,
3396                        const char *new_text_base_path,
3397                        const char *new_text_path,
3398                        apr_hash_t *new_base_props,
3399                        apr_hash_t *new_props,
3400                        const char *copyfrom_url,
3401                        svn_revnum_t copyfrom_rev,
3402                        apr_pool_t *pool)
3403 {
3404   svn_stream_t *new_base_contents;
3405   svn_stream_t *new_contents = NULL;
3406
3407   SVN_ERR(svn_stream_open_readonly(&new_base_contents, new_text_base_path,
3408                                    pool, pool));
3409
3410   if (new_text_path)
3411     {
3412       /* NOTE: the specified path may *not* be under version control.
3413          It is most likely sitting in .svn/tmp/. Thus, we cannot use the
3414          typical WC functions to access "special", "keywords" or "EOL"
3415          information. We need to look at the properties given to us. */
3416
3417       /* If the new file is special, then we can simply open the given
3418          contents since it is already in normal form. */
3419       if (svn_hash_gets(new_props, SVN_PROP_SPECIAL) != NULL)
3420         {
3421           SVN_ERR(svn_stream_open_readonly(&new_contents, new_text_path,
3422                                            pool, pool));
3423         }
3424       else
3425         {
3426           /* The new text contents need to be detrans'd into normal form. */
3427           svn_subst_eol_style_t eol_style;
3428           const char *eol_str;
3429           apr_hash_t *keywords = NULL;
3430           svn_string_t *list;
3431
3432           list = svn_hash_gets(new_props, SVN_PROP_KEYWORDS);
3433           if (list != NULL)
3434             {
3435               /* Since we are detranslating, all of the keyword values
3436                  can be "". */
3437               SVN_ERR(svn_subst_build_keywords2(&keywords,
3438                                                 list->data,
3439                                                 "", "", 0, "",
3440                                                 pool));
3441               if (apr_hash_count(keywords) == 0)
3442                 keywords = NULL;
3443             }
3444
3445           svn_subst_eol_style_from_value(&eol_style, &eol_str,
3446                                          svn_hash_gets(new_props,
3447                                                        SVN_PROP_EOL_STYLE));
3448
3449           if (svn_subst_translation_required(eol_style, eol_str, keywords,
3450                                              FALSE, FALSE))
3451             {
3452               SVN_ERR(svn_subst_stream_detranslated(&new_contents,
3453                                                     new_text_path,
3454                                                     eol_style, eol_str,
3455                                                     FALSE,
3456                                                     keywords,
3457                                                     FALSE,
3458                                                     pool));
3459             }
3460           else
3461             {
3462               SVN_ERR(svn_stream_open_readonly(&new_contents, new_text_path,
3463                                                pool, pool));
3464             }
3465         }
3466     }
3467
3468   SVN_ERR(svn_wc_add_repos_file3(dst_path, adm_access,
3469                                  new_base_contents, new_contents,
3470                                  new_base_props, new_props,
3471                                  copyfrom_url, copyfrom_rev,
3472                                  NULL, NULL, NULL, NULL,
3473                                  pool));
3474
3475   /* The API contract states that the text files will be removed upon
3476      successful completion. add_repos_file3() does not remove the files
3477      since it only has streams on them. Toss 'em now. */
3478   svn_error_clear(svn_io_remove_file(new_text_base_path, pool));
3479   if (new_text_path)
3480     svn_error_clear(svn_io_remove_file(new_text_path, pool));
3481
3482   return SVN_NO_ERROR;
3483 }
3484
3485
3486 svn_error_t *
3487 svn_wc_add_repos_file(const char *dst_path,
3488                       svn_wc_adm_access_t *adm_access,
3489                       const char *new_text_path,
3490                       apr_hash_t *new_props,
3491                       const char *copyfrom_url,
3492                       svn_revnum_t copyfrom_rev,
3493                       apr_pool_t *pool)
3494 {
3495   return svn_wc_add_repos_file2(dst_path, adm_access,
3496                                 new_text_path, NULL,
3497                                 new_props, NULL,
3498                                 copyfrom_url, copyfrom_rev,
3499                                 pool);
3500 }
3501
3502 svn_error_t *
3503 svn_wc_get_actual_target(const char *path,
3504                          const char **anchor,
3505                          const char **target,
3506                          apr_pool_t *pool)
3507 {
3508   svn_wc_context_t *wc_ctx;
3509
3510   SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, pool, pool));
3511   SVN_ERR(svn_wc_get_actual_target2(anchor, target, wc_ctx, path, pool, pool));
3512
3513   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
3514 }
3515
3516 /* This function has no internal variant as its behavior on switched
3517    non-directories is not what you would expect. But this happens to
3518    be the legacy behavior of this function. */
3519 svn_error_t *
3520 svn_wc_is_wc_root2(svn_boolean_t *wc_root,
3521                    svn_wc_context_t *wc_ctx,
3522                    const char *local_abspath,
3523                    apr_pool_t *scratch_pool)
3524 {
3525   svn_boolean_t is_root;
3526   svn_boolean_t is_switched;
3527   svn_node_kind_t kind;
3528   svn_error_t *err;
3529   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
3530
3531   err = svn_wc__db_is_switched(&is_root, &is_switched, &kind,
3532                                wc_ctx->db, local_abspath, scratch_pool);
3533
3534   if (err)
3535     {
3536       if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND &&
3537           err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
3538         return svn_error_trace(err);
3539
3540       return svn_error_create(SVN_ERR_ENTRY_NOT_FOUND, err, err->message);
3541     }
3542
3543   *wc_root = is_root || (kind == svn_node_dir && is_switched);
3544
3545   return SVN_NO_ERROR;
3546 }
3547
3548 svn_error_t *
3549 svn_wc_is_wc_root(svn_boolean_t *wc_root,
3550                   const char *path,
3551                   svn_wc_adm_access_t *adm_access,
3552                   apr_pool_t *pool)
3553 {
3554   svn_wc_context_t *wc_ctx;
3555   const char *local_abspath;
3556   svn_error_t *err;
3557
3558   /* Subversion <= 1.6 said that '.' or a drive root is a WC root. */
3559   if (svn_path_is_empty(path) || svn_dirent_is_root(path, strlen(path)))
3560     {
3561       *wc_root = TRUE;
3562       return SVN_NO_ERROR;
3563     }
3564
3565   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
3566   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
3567                                          svn_wc__adm_get_db(adm_access),
3568                                          pool));
3569
3570   err = svn_wc_is_wc_root2(wc_root, wc_ctx, local_abspath, pool);
3571
3572   if (err
3573       && (err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY
3574           || err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND))
3575     {
3576       /* Subversion <= 1.6 said that an unversioned path is a WC root. */
3577       svn_error_clear(err);
3578       *wc_root = TRUE;
3579     }
3580   else
3581     SVN_ERR(err);
3582
3583   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
3584 }
3585
3586
3587 svn_error_t *
3588 svn_wc_get_update_editor4(const svn_delta_editor_t **editor,
3589                           void **edit_baton,
3590                           svn_revnum_t *target_revision,
3591                           svn_wc_context_t *wc_ctx,
3592                           const char *anchor_abspath,
3593                           const char *target_basename,
3594                           svn_boolean_t use_commit_times,
3595                           svn_depth_t depth,
3596                           svn_boolean_t depth_is_sticky,
3597                           svn_boolean_t allow_unver_obstructions,
3598                           svn_boolean_t adds_as_modification,
3599                           svn_boolean_t server_performs_filtering,
3600                           svn_boolean_t clean_checkout,
3601                           const char *diff3_cmd,
3602                           const apr_array_header_t *preserved_exts,
3603                           svn_wc_dirents_func_t fetch_dirents_func,
3604                           void *fetch_dirents_baton,
3605                           svn_wc_conflict_resolver_func2_t conflict_func,
3606                           void *conflict_baton,
3607                           svn_wc_external_update_t external_func,
3608                           void *external_baton,
3609                           svn_cancel_func_t cancel_func,
3610                           void *cancel_baton,
3611                           svn_wc_notify_func2_t notify_func,
3612                           void *notify_baton,
3613                           apr_pool_t *result_pool,
3614                           apr_pool_t *scratch_pool)
3615 {
3616   return svn_error_trace(
3617     svn_wc__get_update_editor(editor, edit_baton,
3618                               target_revision,
3619                               wc_ctx,
3620                               anchor_abspath,
3621                               target_basename, NULL,
3622                               use_commit_times,
3623                               depth, depth_is_sticky,
3624                               allow_unver_obstructions,
3625                               adds_as_modification,
3626                               server_performs_filtering,
3627                               clean_checkout,
3628                               diff3_cmd,
3629                               preserved_exts,
3630                               fetch_dirents_func, fetch_dirents_baton,
3631                               conflict_func, conflict_baton,
3632                               external_func, external_baton,
3633                               cancel_func, cancel_baton,
3634                               notify_func, notify_baton,
3635                               result_pool, scratch_pool));
3636 }
3637
3638
3639 svn_error_t *
3640 svn_wc_get_update_editor3(svn_revnum_t *target_revision,
3641                           svn_wc_adm_access_t *anchor,
3642                           const char *target,
3643                           svn_boolean_t use_commit_times,
3644                           svn_depth_t depth,
3645                           svn_boolean_t depth_is_sticky,
3646                           svn_boolean_t allow_unver_obstructions,
3647                           svn_wc_notify_func2_t notify_func,
3648                           void *notify_baton,
3649                           svn_cancel_func_t cancel_func,
3650                           void *cancel_baton,
3651                           svn_wc_conflict_resolver_func_t conflict_func,
3652                           void *conflict_baton,
3653                           svn_wc_get_file_t fetch_func,
3654                           void *fetch_baton,
3655                           const char *diff3_cmd,
3656                           const apr_array_header_t *preserved_exts,
3657                           const svn_delta_editor_t **editor,
3658                           void **edit_baton,
3659                           svn_wc_traversal_info_t *traversal_info,
3660                           apr_pool_t *pool)
3661 {
3662   svn_wc_context_t *wc_ctx;
3663   svn_wc__db_t *db = svn_wc__adm_get_db(anchor);
3664   svn_wc_external_update_t external_func = NULL;
3665   struct traversal_info_update_baton *eb = NULL;
3666   struct conflict_func_1to2_baton *cfw = NULL;
3667
3668   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, db, pool));
3669
3670   if (traversal_info)
3671     {
3672       eb = apr_palloc(pool, sizeof(*eb));
3673       eb->db = db;
3674       eb->traversal = traversal_info;
3675       external_func = traversal_info_update;
3676     }
3677
3678   if (conflict_func)
3679     {
3680       cfw = apr_pcalloc(pool, sizeof(*cfw));
3681       cfw->inner_func = conflict_func;
3682       cfw->inner_baton = conflict_baton;
3683     }
3684
3685   if (diff3_cmd)
3686     SVN_ERR(svn_path_cstring_to_utf8(&diff3_cmd, diff3_cmd, pool));
3687
3688   SVN_ERR(svn_wc_get_update_editor4(editor, edit_baton,
3689                                     target_revision,
3690                                     wc_ctx,
3691                                     svn_wc__adm_access_abspath(anchor),
3692                                     target,
3693                                     use_commit_times,
3694                                     depth, depth_is_sticky,
3695                                     allow_unver_obstructions,
3696                                     TRUE /* adds_as_modification */,
3697                                     FALSE /* server_performs_filtering */,
3698                                     FALSE /* clean_checkout */,
3699                                     diff3_cmd,
3700                                     preserved_exts,
3701                                     NULL, NULL, /* fetch_dirents_func, baton */
3702                                     conflict_func ? conflict_func_1to2_wrapper
3703                                                   : NULL,
3704                                     cfw,
3705                                     external_func, eb,
3706                                     cancel_func, cancel_baton,
3707                                     notify_func, notify_baton,
3708                                     pool, pool));
3709
3710   /* We can't destroy wc_ctx here, because the editor needs it while it's
3711      driven. */
3712   return SVN_NO_ERROR;
3713 }
3714
3715 svn_error_t *
3716 svn_wc_get_update_editor2(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_func2_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   return svn_wc_get_update_editor3(target_revision, anchor, target,
3732                                    use_commit_times,
3733                                    SVN_DEPTH_INFINITY_OR_FILES(recurse), FALSE,
3734                                    FALSE, notify_func, notify_baton,
3735                                    cancel_func, cancel_baton, NULL, NULL,
3736                                    NULL, NULL,
3737                                    diff3_cmd, NULL, editor, edit_baton,
3738                                    traversal_info, pool);
3739 }
3740
3741 svn_error_t *
3742 svn_wc_get_update_editor(svn_revnum_t *target_revision,
3743                          svn_wc_adm_access_t *anchor,
3744                          const char *target,
3745                          svn_boolean_t use_commit_times,
3746                          svn_boolean_t recurse,
3747                          svn_wc_notify_func_t notify_func,
3748                          void *notify_baton,
3749                          svn_cancel_func_t cancel_func,
3750                          void *cancel_baton,
3751                          const char *diff3_cmd,
3752                          const svn_delta_editor_t **editor,
3753                          void **edit_baton,
3754                          svn_wc_traversal_info_t *traversal_info,
3755                          apr_pool_t *pool)
3756 {
3757   /* This baton must live beyond this function. Alloc on heap.  */
3758   struct compat_notify_baton_t *nb = apr_palloc(pool, sizeof(*nb));
3759
3760   nb->func = notify_func;
3761   nb->baton = notify_baton;
3762
3763   return svn_wc_get_update_editor3(target_revision, anchor, target,
3764                                    use_commit_times,
3765                                    SVN_DEPTH_INFINITY_OR_FILES(recurse), FALSE,
3766                                    FALSE, compat_call_notify_func, nb,
3767                                    cancel_func, cancel_baton, NULL, NULL,
3768                                    NULL, NULL,
3769                                    diff3_cmd, NULL, editor, edit_baton,
3770                                    traversal_info, pool);
3771 }
3772
3773
3774 svn_error_t *
3775 svn_wc_get_switch_editor4(const svn_delta_editor_t **editor,
3776                           void **edit_baton,
3777                           svn_revnum_t *target_revision,
3778                           svn_wc_context_t *wc_ctx,
3779                           const char *anchor_abspath,
3780                           const char *target_basename,
3781                           const char *switch_url,
3782                           svn_boolean_t use_commit_times,
3783                           svn_depth_t depth,
3784                           svn_boolean_t depth_is_sticky,
3785                           svn_boolean_t allow_unver_obstructions,
3786                           svn_boolean_t server_performs_filtering,
3787                           const char *diff3_cmd,
3788                           const apr_array_header_t *preserved_exts,
3789                           svn_wc_dirents_func_t fetch_dirents_func,
3790                           void *fetch_dirents_baton,
3791                           svn_wc_conflict_resolver_func2_t conflict_func,
3792                           void *conflict_baton,
3793                           svn_wc_external_update_t external_func,
3794                           void *external_baton,
3795                           svn_cancel_func_t cancel_func,
3796                           void *cancel_baton,
3797                           svn_wc_notify_func2_t notify_func,
3798                           void *notify_baton,
3799                           apr_pool_t *result_pool,
3800                           apr_pool_t *scratch_pool)
3801 {
3802   return svn_error_trace(
3803     svn_wc__get_switch_editor(editor, edit_baton,
3804                               target_revision,
3805                               wc_ctx,
3806                               anchor_abspath, target_basename,
3807                               switch_url, NULL,
3808                               use_commit_times,
3809                               depth, depth_is_sticky,
3810                               allow_unver_obstructions,
3811                               server_performs_filtering,
3812                               diff3_cmd,
3813                               preserved_exts,
3814                               fetch_dirents_func, fetch_dirents_baton,
3815                               conflict_func, conflict_baton,
3816                               external_func, external_baton,
3817                               cancel_func, cancel_baton,
3818                               notify_func, notify_baton,
3819                               result_pool, scratch_pool));
3820 }
3821
3822
3823 svn_error_t *
3824 svn_wc_get_switch_editor3(svn_revnum_t *target_revision,
3825                           svn_wc_adm_access_t *anchor,
3826                           const char *target,
3827                           const char *switch_url,
3828                           svn_boolean_t use_commit_times,
3829                           svn_depth_t depth,
3830                           svn_boolean_t depth_is_sticky,
3831                           svn_boolean_t allow_unver_obstructions,
3832                           svn_wc_notify_func2_t notify_func,
3833                           void *notify_baton,
3834                           svn_cancel_func_t cancel_func,
3835                           void *cancel_baton,
3836                           svn_wc_conflict_resolver_func_t conflict_func,
3837                           void *conflict_baton,
3838                           const char *diff3_cmd,
3839                           const apr_array_header_t *preserved_exts,
3840                           const svn_delta_editor_t **editor,
3841                           void **edit_baton,
3842                           svn_wc_traversal_info_t *traversal_info,
3843                           apr_pool_t *pool)
3844 {
3845   svn_wc_context_t *wc_ctx;
3846   svn_wc__db_t *db = svn_wc__adm_get_db(anchor);
3847   svn_wc_external_update_t external_func = NULL;
3848   struct traversal_info_update_baton *eb = NULL;
3849   struct conflict_func_1to2_baton *cfw = NULL;
3850
3851   SVN_ERR_ASSERT(switch_url && svn_uri_is_canonical(switch_url, pool));
3852
3853   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, db, pool));
3854
3855   if (traversal_info)
3856     {
3857       eb = apr_palloc(pool, sizeof(*eb));
3858       eb->db = db;
3859       eb->traversal = traversal_info;
3860       external_func = traversal_info_update;
3861     }
3862
3863   if (conflict_func)
3864     {
3865       cfw = apr_pcalloc(pool, sizeof(*cfw));
3866       cfw->inner_func = conflict_func;
3867       cfw->inner_baton = conflict_baton;
3868     }
3869
3870   if (diff3_cmd)
3871     SVN_ERR(svn_path_cstring_to_utf8(&diff3_cmd, diff3_cmd, pool));
3872
3873   SVN_ERR(svn_wc_get_switch_editor4(editor, edit_baton,
3874                                     target_revision,
3875                                     wc_ctx,
3876                                     svn_wc__adm_access_abspath(anchor),
3877                                     target, switch_url,
3878                                     use_commit_times,
3879                                     depth, depth_is_sticky,
3880                                     allow_unver_obstructions,
3881                                     FALSE /* server_performs_filtering */,
3882                                     diff3_cmd,
3883                                     preserved_exts,
3884                                     NULL, NULL, /* fetch_dirents_func, baton */
3885                                     conflict_func ? conflict_func_1to2_wrapper
3886                                                   : NULL,
3887                                     cfw,
3888                                     external_func, eb,
3889                                     cancel_func, cancel_baton,
3890                                     notify_func, notify_baton,
3891                                     pool, pool));
3892
3893   /* We can't destroy wc_ctx here, because the editor needs it while it's
3894      driven. */
3895   return SVN_NO_ERROR;
3896 }
3897
3898 svn_error_t *
3899 svn_wc_get_switch_editor2(svn_revnum_t *target_revision,
3900                           svn_wc_adm_access_t *anchor,
3901                           const char *target,
3902                           const char *switch_url,
3903                           svn_boolean_t use_commit_times,
3904                           svn_boolean_t recurse,
3905                           svn_wc_notify_func2_t notify_func,
3906                           void *notify_baton,
3907                           svn_cancel_func_t cancel_func,
3908                           void *cancel_baton,
3909                           const char *diff3_cmd,
3910                           const svn_delta_editor_t **editor,
3911                           void **edit_baton,
3912                           svn_wc_traversal_info_t *traversal_info,
3913                           apr_pool_t *pool)
3914 {
3915   SVN_ERR_ASSERT(switch_url);
3916
3917   return svn_wc_get_switch_editor3(target_revision, anchor, target,
3918                                    switch_url, use_commit_times,
3919                                    SVN_DEPTH_INFINITY_OR_FILES(recurse), FALSE,
3920                                    FALSE, notify_func, notify_baton,
3921                                    cancel_func, cancel_baton,
3922                                    NULL, NULL, diff3_cmd,
3923                                    NULL, editor, edit_baton, traversal_info,
3924                                    pool);
3925 }
3926
3927 svn_error_t *
3928 svn_wc_get_switch_editor(svn_revnum_t *target_revision,
3929                          svn_wc_adm_access_t *anchor,
3930                          const char *target,
3931                          const char *switch_url,
3932                          svn_boolean_t use_commit_times,
3933                          svn_boolean_t recurse,
3934                          svn_wc_notify_func_t notify_func,
3935                          void *notify_baton,
3936                          svn_cancel_func_t cancel_func,
3937                          void *cancel_baton,
3938                          const char *diff3_cmd,
3939                          const svn_delta_editor_t **editor,
3940                          void **edit_baton,
3941                          svn_wc_traversal_info_t *traversal_info,
3942                          apr_pool_t *pool)
3943 {
3944   /* This baton must live beyond this function. Alloc on heap.  */
3945   struct compat_notify_baton_t *nb = apr_palloc(pool, sizeof(*nb));
3946
3947   nb->func = notify_func;
3948   nb->baton = notify_baton;
3949
3950   return svn_wc_get_switch_editor3(target_revision, anchor, target,
3951                                    switch_url, use_commit_times,
3952                                    SVN_DEPTH_INFINITY_OR_FILES(recurse), FALSE,
3953                                    FALSE, compat_call_notify_func, nb,
3954                                    cancel_func, cancel_baton,
3955                                    NULL, NULL, diff3_cmd,
3956                                    NULL, editor, edit_baton, traversal_info,
3957                                    pool);
3958 }
3959
3960
3961 svn_error_t *
3962 svn_wc_external_item_create(const svn_wc_external_item2_t **item,
3963                             apr_pool_t *pool)
3964 {
3965   *item = apr_pcalloc(pool, sizeof(svn_wc_external_item2_t));
3966   return SVN_NO_ERROR;
3967 }
3968
3969 svn_wc_external_item_t *
3970 svn_wc_external_item_dup(const svn_wc_external_item_t *item,
3971                          apr_pool_t *pool)
3972 {
3973   svn_wc_external_item_t *new_item = apr_palloc(pool, sizeof(*new_item));
3974
3975   *new_item = *item;
3976
3977   if (new_item->target_dir)
3978     new_item->target_dir = apr_pstrdup(pool, new_item->target_dir);
3979
3980   if (new_item->url)
3981     new_item->url = apr_pstrdup(pool, new_item->url);
3982
3983   return new_item;
3984 }
3985
3986
3987 svn_wc_traversal_info_t *
3988 svn_wc_init_traversal_info(apr_pool_t *pool)
3989 {
3990   svn_wc_traversal_info_t *ti = apr_palloc(pool, sizeof(*ti));
3991
3992   ti->pool           = pool;
3993   ti->externals_old  = apr_hash_make(pool);
3994   ti->externals_new  = apr_hash_make(pool);
3995   ti->depths         = apr_hash_make(pool);
3996
3997   return ti;
3998 }
3999
4000
4001 void
4002 svn_wc_edited_externals(apr_hash_t **externals_old,
4003                         apr_hash_t **externals_new,
4004                         svn_wc_traversal_info_t *traversal_info)
4005 {
4006   *externals_old = traversal_info->externals_old;
4007   *externals_new = traversal_info->externals_new;
4008 }
4009
4010
4011 void
4012 svn_wc_traversed_depths(apr_hash_t **depths,
4013                         svn_wc_traversal_info_t *traversal_info)
4014 {
4015   *depths = traversal_info->depths;
4016 }
4017
4018
4019 /*** From lock.c ***/
4020
4021 /* To preserve API compatibility with Subversion 1.0.0 */
4022 svn_error_t *
4023 svn_wc_adm_open(svn_wc_adm_access_t **adm_access,
4024                 svn_wc_adm_access_t *associated,
4025                 const char *path,
4026                 svn_boolean_t write_lock,
4027                 svn_boolean_t tree_lock,
4028                 apr_pool_t *pool)
4029 {
4030   return svn_wc_adm_open3(adm_access, associated, path, write_lock,
4031                           (tree_lock ? -1 : 0), NULL, NULL, pool);
4032 }
4033
4034 svn_error_t *
4035 svn_wc_adm_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_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_open(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                       svn_boolean_t tree_lock,
4052                       apr_pool_t *pool)
4053 {
4054   return svn_wc_adm_probe_open3(adm_access, associated, path,
4055                                 write_lock, (tree_lock ? -1 : 0),
4056                                 NULL, NULL, pool);
4057 }
4058
4059
4060 svn_error_t *
4061 svn_wc_adm_probe_open2(svn_wc_adm_access_t **adm_access,
4062                        svn_wc_adm_access_t *associated,
4063                        const char *path,
4064                        svn_boolean_t write_lock,
4065                        int levels_to_lock,
4066                        apr_pool_t *pool)
4067 {
4068   return svn_wc_adm_probe_open3(adm_access, associated, path, write_lock,
4069                                 levels_to_lock, NULL, NULL, pool);
4070 }
4071
4072 svn_error_t *
4073 svn_wc_adm_probe_try2(svn_wc_adm_access_t **adm_access,
4074                       svn_wc_adm_access_t *associated,
4075                       const char *path,
4076                       svn_boolean_t write_lock,
4077                       int levels_to_lock,
4078                       apr_pool_t *pool)
4079 {
4080   return svn_wc_adm_probe_try3(adm_access, associated, path, write_lock,
4081                                levels_to_lock, NULL, NULL, pool);
4082 }
4083
4084 svn_error_t *
4085 svn_wc_adm_probe_try(svn_wc_adm_access_t **adm_access,
4086                      svn_wc_adm_access_t *associated,
4087                      const char *path,
4088                      svn_boolean_t write_lock,
4089                      svn_boolean_t tree_lock,
4090                      apr_pool_t *pool)
4091 {
4092   return svn_wc_adm_probe_try3(adm_access, associated, path, write_lock,
4093                                (tree_lock ? -1 : 0), NULL, NULL, pool);
4094 }
4095
4096 svn_error_t *
4097 svn_wc_adm_close(svn_wc_adm_access_t *adm_access)
4098 {
4099   /* This is the only pool we have access to. */
4100   apr_pool_t *scratch_pool = svn_wc_adm_access_pool(adm_access);
4101
4102   return svn_wc_adm_close2(adm_access, scratch_pool);
4103 }
4104
4105 svn_error_t *
4106 svn_wc_locked(svn_boolean_t *locked,
4107               const char *path,
4108               apr_pool_t *pool)
4109 {
4110   svn_wc_context_t *wc_ctx;
4111   const char *local_abspath;
4112
4113   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
4114   SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, pool, pool));
4115
4116   SVN_ERR(svn_wc_locked2(NULL, locked, wc_ctx, local_abspath, pool));
4117
4118   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4119 }
4120
4121 svn_error_t *
4122 svn_wc_check_wc(const char *path,
4123                 int *wc_format,
4124                 apr_pool_t *pool)
4125 {
4126   svn_wc_context_t *wc_ctx;
4127   const char *local_abspath;
4128
4129   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
4130   SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, pool, pool));
4131
4132   SVN_ERR(svn_wc_check_wc2(wc_format, wc_ctx, local_abspath, pool));
4133
4134   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4135 }
4136
4137
4138 /*** From translate.c ***/
4139
4140 svn_error_t *
4141 svn_wc_translated_file(const char **xlated_p,
4142                        const char *vfile,
4143                        svn_wc_adm_access_t *adm_access,
4144                        svn_boolean_t force_repair,
4145                        apr_pool_t *pool)
4146 {
4147   return svn_wc_translated_file2(xlated_p, vfile, vfile, adm_access,
4148                                  SVN_WC_TRANSLATE_TO_NF
4149                                  | (force_repair ?
4150                                     SVN_WC_TRANSLATE_FORCE_EOL_REPAIR : 0),
4151                                  pool);
4152 }
4153
4154 svn_error_t *
4155 svn_wc_translated_stream(svn_stream_t **stream,
4156                          const char *path,
4157                          const char *versioned_file,
4158                          svn_wc_adm_access_t *adm_access,
4159                          apr_uint32_t flags,
4160                          apr_pool_t *pool)
4161 {
4162   const char *local_abspath;
4163   const char *versioned_abspath;
4164
4165   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
4166   SVN_ERR(svn_dirent_get_absolute(&versioned_abspath, versioned_file, pool));
4167
4168   return svn_error_trace(
4169     svn_wc__internal_translated_stream(stream, svn_wc__adm_get_db(adm_access),
4170                                        local_abspath, versioned_abspath, flags,
4171                                        pool, pool));
4172 }
4173
4174 svn_error_t *
4175 svn_wc_translated_file2(const char **xlated_path,
4176                         const char *src,
4177                         const char *versioned_file,
4178                         svn_wc_adm_access_t *adm_access,
4179                         apr_uint32_t flags,
4180                         apr_pool_t *pool)
4181 {
4182   const char *versioned_abspath;
4183   const char *root;
4184   const char *tmp_root;
4185   const char *src_abspath;
4186
4187   SVN_ERR(svn_dirent_get_absolute(&versioned_abspath, versioned_file, pool));
4188   SVN_ERR(svn_dirent_get_absolute(&src_abspath, src, pool));
4189
4190   SVN_ERR(svn_wc__internal_translated_file(xlated_path, src_abspath,
4191                                            svn_wc__adm_get_db(adm_access),
4192                                            versioned_abspath,
4193                                            flags, NULL, NULL, pool, pool));
4194
4195   if (strcmp(*xlated_path, src_abspath) == 0)
4196     *xlated_path = src;
4197   else if (! svn_dirent_is_absolute(versioned_file))
4198     {
4199       SVN_ERR(svn_io_temp_dir(&tmp_root, pool));
4200       if (! svn_dirent_is_child(tmp_root, *xlated_path, pool))
4201         {
4202           SVN_ERR(svn_dirent_get_absolute(&root, "", pool));
4203
4204           if (svn_dirent_is_child(root, *xlated_path, pool))
4205             *xlated_path = svn_dirent_is_child(root, *xlated_path, pool);
4206         }
4207     }
4208
4209   return SVN_NO_ERROR;
4210 }
4211
4212 /*** From relocate.c ***/
4213 svn_error_t *
4214 svn_wc_relocate3(const char *path,
4215                  svn_wc_adm_access_t *adm_access,
4216                  const char *from,
4217                  const char *to,
4218                  svn_boolean_t recurse,
4219                  svn_wc_relocation_validator3_t validator,
4220                  void *validator_baton,
4221                  apr_pool_t *pool)
4222 {
4223   const char *local_abspath;
4224   svn_wc_context_t *wc_ctx;
4225
4226   if (! recurse)
4227     SVN_ERR(svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
4228                              _("Non-recursive relocation not supported")));
4229
4230   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
4231   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
4232                                          svn_wc__adm_get_db(adm_access),
4233                                          pool));
4234
4235   SVN_ERR(svn_wc_relocate4(wc_ctx, local_abspath, from, to,
4236                            validator, validator_baton, pool));
4237
4238   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4239 }
4240
4241 /* Compatibility baton and wrapper. */
4242 struct compat2_baton {
4243   svn_wc_relocation_validator2_t validator;
4244   void *baton;
4245 };
4246
4247 /* Compatibility baton and wrapper. */
4248 struct compat_baton {
4249   svn_wc_relocation_validator_t validator;
4250   void *baton;
4251 };
4252
4253 /* This implements svn_wc_relocate_validator3_t. */
4254 static svn_error_t *
4255 compat2_validator(void *baton,
4256                   const char *uuid,
4257                   const char *url,
4258                   const char *root_url,
4259                   apr_pool_t *pool)
4260 {
4261   struct compat2_baton *cb = baton;
4262   /* The old callback type doesn't set root_url. */
4263   return cb->validator(cb->baton, uuid,
4264                        (root_url ? root_url : url), (root_url != NULL),
4265                        pool);
4266 }
4267
4268 /* This implements svn_wc_relocate_validator3_t. */
4269 static svn_error_t *
4270 compat_validator(void *baton,
4271                  const char *uuid,
4272                  const char *url,
4273                  const char *root_url,
4274                  apr_pool_t *pool)
4275 {
4276   struct compat_baton *cb = baton;
4277   /* The old callback type doesn't allow uuid to be NULL. */
4278   if (uuid)
4279     return cb->validator(cb->baton, uuid, url);
4280   return SVN_NO_ERROR;
4281 }
4282
4283 svn_error_t *
4284 svn_wc_relocate2(const char *path,
4285                  svn_wc_adm_access_t *adm_access,
4286                  const char *from,
4287                  const char *to,
4288                  svn_boolean_t recurse,
4289                  svn_wc_relocation_validator2_t validator,
4290                  void *validator_baton,
4291                  apr_pool_t *pool)
4292 {
4293   struct compat2_baton cb;
4294
4295   cb.validator = validator;
4296   cb.baton = validator_baton;
4297
4298   return svn_wc_relocate3(path, adm_access, from, to, recurse,
4299                           compat2_validator, &cb, pool);
4300 }
4301
4302 svn_error_t *
4303 svn_wc_relocate(const char *path,
4304                 svn_wc_adm_access_t *adm_access,
4305                 const char *from,
4306                 const char *to,
4307                 svn_boolean_t recurse,
4308                 svn_wc_relocation_validator_t validator,
4309                 void *validator_baton,
4310                 apr_pool_t *pool)
4311 {
4312   struct compat_baton cb;
4313
4314   cb.validator = validator;
4315   cb.baton = validator_baton;
4316
4317   return svn_wc_relocate3(path, adm_access, from, to, recurse,
4318                           compat_validator, &cb, pool);
4319 }
4320
4321
4322 /*** From log.c / cleanup.c ***/
4323
4324 svn_error_t *
4325 svn_wc_cleanup3(svn_wc_context_t *wc_ctx,
4326                 const char *local_abspath,
4327                 svn_cancel_func_t cancel_func,
4328                 void *cancel_baton,
4329                 apr_pool_t *scratch_pool)
4330 {
4331   return svn_error_trace(
4332             svn_wc_cleanup4(wc_ctx,
4333                             local_abspath,
4334                             TRUE /* break_locks */,
4335                             TRUE /* fix_recorded_timestamps */,
4336                             TRUE /* clear_dav_cache */,
4337                             TRUE /* clean_pristines */,
4338                             cancel_func, cancel_baton,
4339                             NULL, NULL /* notify */,
4340                             scratch_pool));
4341 }
4342
4343 svn_error_t *
4344 svn_wc_cleanup2(const char *path,
4345                 const char *diff3_cmd,
4346                 svn_cancel_func_t cancel_func,
4347                 void *cancel_baton,
4348                 apr_pool_t *pool)
4349 {
4350   svn_wc_context_t *wc_ctx;
4351   const char *local_abspath;
4352
4353   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
4354   SVN_ERR(svn_wc_context_create(&wc_ctx, NULL, pool, pool));
4355
4356   SVN_ERR(svn_wc_cleanup3(wc_ctx, local_abspath, cancel_func,
4357                           cancel_baton, pool));
4358
4359   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4360 }
4361
4362 svn_error_t *
4363 svn_wc_cleanup(const char *path,
4364                svn_wc_adm_access_t *optional_adm_access,
4365                const char *diff3_cmd,
4366                svn_cancel_func_t cancel_func,
4367                void *cancel_baton,
4368                apr_pool_t *pool)
4369 {
4370   return svn_wc_cleanup2(path, diff3_cmd, cancel_func, cancel_baton, pool);
4371 }
4372
4373 /*** From questions.c ***/
4374
4375 svn_error_t *
4376 svn_wc_has_binary_prop(svn_boolean_t *has_binary_prop,
4377                        const char *path,
4378                        svn_wc_adm_access_t *adm_access,
4379                        apr_pool_t *pool)
4380 {
4381   svn_wc__db_t *db = svn_wc__adm_get_db(adm_access);
4382   const char *local_abspath;
4383   const svn_string_t *value;
4384
4385   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
4386
4387   SVN_ERR(svn_wc__internal_propget(&value, db, local_abspath,
4388                                    SVN_PROP_MIME_TYPE,
4389                                    pool, pool));
4390
4391   if (value && (svn_mime_type_is_binary(value->data)))
4392     *has_binary_prop = TRUE;
4393   else
4394     *has_binary_prop = FALSE;
4395
4396   return SVN_NO_ERROR;
4397 }
4398
4399 svn_error_t *
4400 svn_wc_conflicted_p2(svn_boolean_t *text_conflicted_p,
4401                      svn_boolean_t *prop_conflicted_p,
4402                      svn_boolean_t *tree_conflicted_p,
4403                      const char *path,
4404                      svn_wc_adm_access_t *adm_access,
4405                      apr_pool_t *pool)
4406 {
4407   const char *local_abspath;
4408   svn_wc_context_t *wc_ctx;
4409   svn_error_t *err;
4410
4411   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
4412   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */,
4413                                          svn_wc__adm_get_db(adm_access),
4414                                          pool));
4415
4416   err = svn_wc_conflicted_p3(text_conflicted_p, prop_conflicted_p,
4417                              tree_conflicted_p, wc_ctx, local_abspath, pool);
4418
4419   if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
4420     {
4421       svn_error_clear(err);
4422
4423       if (text_conflicted_p)
4424         *text_conflicted_p = FALSE;
4425       if (prop_conflicted_p)
4426         *prop_conflicted_p = FALSE;
4427       if (tree_conflicted_p)
4428         *tree_conflicted_p = FALSE;
4429     }
4430   else if (err)
4431     return err;
4432
4433   return SVN_NO_ERROR;
4434 }
4435
4436 svn_error_t *
4437 svn_wc_conflicted_p(svn_boolean_t *text_conflicted_p,
4438                     svn_boolean_t *prop_conflicted_p,
4439                     const char *dir_path,
4440                     const svn_wc_entry_t *entry,
4441                     apr_pool_t *pool)
4442 {
4443   svn_node_kind_t kind;
4444   const char *path;
4445
4446   *text_conflicted_p = FALSE;
4447   *prop_conflicted_p = FALSE;
4448
4449   if (entry->conflict_old)
4450     {
4451       path = svn_dirent_join(dir_path, entry->conflict_old, pool);
4452       SVN_ERR(svn_io_check_path(path, &kind, pool));
4453       *text_conflicted_p = (kind == svn_node_file);
4454     }
4455
4456   if ((! *text_conflicted_p) && (entry->conflict_new))
4457     {
4458       path = svn_dirent_join(dir_path, entry->conflict_new, pool);
4459       SVN_ERR(svn_io_check_path(path, &kind, pool));
4460       *text_conflicted_p = (kind == svn_node_file);
4461     }
4462
4463   if ((! *text_conflicted_p) && (entry->conflict_wrk))
4464     {
4465       path = svn_dirent_join(dir_path, entry->conflict_wrk, pool);
4466       SVN_ERR(svn_io_check_path(path, &kind, pool));
4467       *text_conflicted_p = (kind == svn_node_file);
4468     }
4469
4470   if (entry->prejfile)
4471     {
4472       path = svn_dirent_join(dir_path, entry->prejfile, pool);
4473       SVN_ERR(svn_io_check_path(path, &kind, pool));
4474       *prop_conflicted_p = (kind == svn_node_file);
4475     }
4476
4477   return SVN_NO_ERROR;
4478 }
4479
4480 svn_error_t *
4481 svn_wc_text_modified_p(svn_boolean_t *modified_p,
4482                        const char *filename,
4483                        svn_boolean_t force_comparison,
4484                        svn_wc_adm_access_t *adm_access,
4485                        apr_pool_t *pool)
4486 {
4487   svn_wc_context_t *wc_ctx;
4488   svn_wc__db_t *db = svn_wc__adm_get_db(adm_access);
4489   const char *local_abspath;
4490
4491   SVN_ERR(svn_dirent_get_absolute(&local_abspath, filename, pool));
4492   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, db, pool));
4493
4494   SVN_ERR(svn_wc_text_modified_p2(modified_p, wc_ctx, local_abspath,
4495                                   force_comparison, pool));
4496
4497   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4498 }
4499
4500
4501 /*** From copy.c ***/
4502 svn_error_t *
4503 svn_wc_copy2(const char *src,
4504              svn_wc_adm_access_t *dst_parent,
4505              const char *dst_basename,
4506              svn_cancel_func_t cancel_func,
4507              void *cancel_baton,
4508              svn_wc_notify_func2_t notify_func,
4509              void *notify_baton,
4510              apr_pool_t *pool)
4511 {
4512   svn_wc_context_t *wc_ctx;
4513   svn_wc__db_t *wc_db = svn_wc__adm_get_db(dst_parent);
4514   const char *src_abspath;
4515   const char *dst_abspath;
4516
4517   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, wc_db, pool));
4518   SVN_ERR(svn_dirent_get_absolute(&src_abspath, src, pool));
4519
4520   dst_abspath = svn_dirent_join(svn_wc__adm_access_abspath(dst_parent),
4521                                 dst_basename, pool);
4522
4523   SVN_ERR(svn_wc_copy3(wc_ctx,
4524                        src_abspath,
4525                        dst_abspath,
4526                        FALSE /* metadata_only */,
4527                        cancel_func, cancel_baton,
4528                        notify_func, notify_baton,
4529                        pool));
4530
4531   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4532 }
4533
4534 svn_error_t *
4535 svn_wc_copy(const char *src_path,
4536             svn_wc_adm_access_t *dst_parent,
4537             const char *dst_basename,
4538             svn_cancel_func_t cancel_func,
4539             void *cancel_baton,
4540             svn_wc_notify_func_t notify_func,
4541             void *notify_baton,
4542             apr_pool_t *pool)
4543 {
4544   struct compat_notify_baton_t nb;
4545
4546   nb.func = notify_func;
4547   nb.baton = notify_baton;
4548
4549   return svn_wc_copy2(src_path, dst_parent, dst_basename, cancel_func,
4550                       cancel_baton, compat_call_notify_func,
4551                       &nb, pool);
4552 }
4553
4554
4555 /*** From merge.c ***/
4556
4557 svn_error_t *
4558 svn_wc_merge4(enum svn_wc_merge_outcome_t *merge_outcome,
4559               svn_wc_context_t *wc_ctx,
4560               const char *left_abspath,
4561               const char *right_abspath,
4562               const char *target_abspath,
4563               const char *left_label,
4564               const char *right_label,
4565               const char *target_label,
4566               const svn_wc_conflict_version_t *left_version,
4567               const svn_wc_conflict_version_t *right_version,
4568               svn_boolean_t dry_run,
4569               const char *diff3_cmd,
4570               const apr_array_header_t *merge_options,
4571               const apr_array_header_t *prop_diff,
4572               svn_wc_conflict_resolver_func2_t conflict_func,
4573               void *conflict_baton,
4574               svn_cancel_func_t cancel_func,
4575               void *cancel_baton,
4576               apr_pool_t *scratch_pool)
4577 {
4578   return svn_error_trace(
4579             svn_wc_merge5(merge_outcome,
4580                           NULL /* merge_props_outcome */,
4581                           wc_ctx,
4582                           left_abspath,
4583                           right_abspath,
4584                           target_abspath,
4585                           left_label,
4586                           right_label,
4587                           target_label,
4588                           left_version,
4589                           right_version,
4590                           dry_run,
4591                           diff3_cmd,
4592                           merge_options,
4593                           NULL /* original_props */,
4594                           prop_diff,
4595                           conflict_func, conflict_baton,
4596                           cancel_func, cancel_baton,
4597                           scratch_pool));
4598 }
4599
4600 svn_error_t *
4601 svn_wc_merge3(enum svn_wc_merge_outcome_t *merge_outcome,
4602               const char *left,
4603               const char *right,
4604               const char *merge_target,
4605               svn_wc_adm_access_t *adm_access,
4606               const char *left_label,
4607               const char *right_label,
4608               const char *target_label,
4609               svn_boolean_t dry_run,
4610               const char *diff3_cmd,
4611               const apr_array_header_t *merge_options,
4612               const apr_array_header_t *prop_diff,
4613               svn_wc_conflict_resolver_func_t conflict_func,
4614               void *conflict_baton,
4615               apr_pool_t *pool)
4616 {
4617   svn_wc_context_t *wc_ctx;
4618   svn_wc__db_t *db = svn_wc__adm_get_db(adm_access);
4619   const char *left_abspath, *right_abspath, *target_abspath;
4620   struct conflict_func_1to2_baton cfw;
4621
4622   SVN_ERR(svn_dirent_get_absolute(&left_abspath, left, pool));
4623   SVN_ERR(svn_dirent_get_absolute(&right_abspath, right, pool));
4624   SVN_ERR(svn_dirent_get_absolute(&target_abspath, merge_target, pool));
4625
4626   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */, db, pool));
4627
4628   cfw.inner_func = conflict_func;
4629   cfw.inner_baton = conflict_baton;
4630
4631   if (diff3_cmd)
4632     SVN_ERR(svn_path_cstring_to_utf8(&diff3_cmd, diff3_cmd, pool));
4633
4634   SVN_ERR(svn_wc_merge4(merge_outcome,
4635                         wc_ctx,
4636                         left_abspath,
4637                         right_abspath,
4638                         target_abspath,
4639                         left_label,
4640                         right_label,
4641                         target_label,
4642                         NULL,
4643                         NULL,
4644                         dry_run,
4645                         diff3_cmd,
4646                         merge_options,
4647                         prop_diff,
4648                         conflict_func ? conflict_func_1to2_wrapper : NULL,
4649                         &cfw,
4650                         NULL, NULL,
4651                         pool));
4652
4653   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4654 }
4655
4656 svn_error_t *
4657 svn_wc_merge2(enum svn_wc_merge_outcome_t *merge_outcome,
4658               const char *left,
4659               const char *right,
4660               const char *merge_target,
4661               svn_wc_adm_access_t *adm_access,
4662               const char *left_label,
4663               const char *right_label,
4664               const char *target_label,
4665               svn_boolean_t dry_run,
4666               const char *diff3_cmd,
4667               const apr_array_header_t *merge_options,
4668               apr_pool_t *pool)
4669 {
4670   return svn_wc_merge3(merge_outcome,
4671                        left, right, merge_target, adm_access,
4672                        left_label, right_label, target_label,
4673                        dry_run, diff3_cmd, merge_options, NULL,
4674                        NULL, NULL, pool);
4675 }
4676
4677 svn_error_t *
4678 svn_wc_merge(const char *left,
4679              const char *right,
4680              const char *merge_target,
4681              svn_wc_adm_access_t *adm_access,
4682              const char *left_label,
4683              const char *right_label,
4684              const char *target_label,
4685              svn_boolean_t dry_run,
4686              enum svn_wc_merge_outcome_t *merge_outcome,
4687              const char *diff3_cmd,
4688              apr_pool_t *pool)
4689 {
4690   return svn_wc_merge3(merge_outcome,
4691                        left, right, merge_target, adm_access,
4692                        left_label, right_label, target_label,
4693                        dry_run, diff3_cmd, NULL, NULL, NULL,
4694                        NULL, pool);
4695 }
4696
4697
4698 /*** From util.c ***/
4699
4700 svn_wc_conflict_version_t *
4701 svn_wc_conflict_version_create(const char *repos_url,
4702                                const char *path_in_repos,
4703                                svn_revnum_t peg_rev,
4704                                svn_node_kind_t node_kind,
4705                                apr_pool_t *pool)
4706 {
4707   return svn_wc_conflict_version_create2(repos_url, NULL, path_in_repos,
4708                                          peg_rev, node_kind, pool);
4709 }
4710
4711 svn_wc_conflict_description_t *
4712 svn_wc_conflict_description_create_text(const char *path,
4713                                         svn_wc_adm_access_t *adm_access,
4714                                         apr_pool_t *pool)
4715 {
4716   svn_wc_conflict_description_t *conflict;
4717
4718   conflict = apr_pcalloc(pool, sizeof(*conflict));
4719   conflict->path = path;
4720   conflict->node_kind = svn_node_file;
4721   conflict->kind = svn_wc_conflict_kind_text;
4722   conflict->access = adm_access;
4723   conflict->action = svn_wc_conflict_action_edit;
4724   conflict->reason = svn_wc_conflict_reason_edited;
4725   return conflict;
4726 }
4727
4728 svn_wc_conflict_description_t *
4729 svn_wc_conflict_description_create_prop(const char *path,
4730                                         svn_wc_adm_access_t *adm_access,
4731                                         svn_node_kind_t node_kind,
4732                                         const char *property_name,
4733                                         apr_pool_t *pool)
4734 {
4735   svn_wc_conflict_description_t *conflict;
4736
4737   conflict = apr_pcalloc(pool, sizeof(*conflict));
4738   conflict->path = path;
4739   conflict->node_kind = node_kind;
4740   conflict->kind = svn_wc_conflict_kind_property;
4741   conflict->access = adm_access;
4742   conflict->property_name = property_name;
4743   return conflict;
4744 }
4745
4746 svn_wc_conflict_description_t *
4747 svn_wc_conflict_description_create_tree(
4748                             const char *path,
4749                             svn_wc_adm_access_t *adm_access,
4750                             svn_node_kind_t node_kind,
4751                             svn_wc_operation_t operation,
4752                             svn_wc_conflict_version_t *src_left_version,
4753                             svn_wc_conflict_version_t *src_right_version,
4754                             apr_pool_t *pool)
4755 {
4756   svn_wc_conflict_description_t *conflict;
4757
4758   conflict = apr_pcalloc(pool, sizeof(*conflict));
4759   conflict->path = path;
4760   conflict->node_kind = node_kind;
4761   conflict->kind = svn_wc_conflict_kind_tree;
4762   conflict->access = adm_access;
4763   conflict->operation = operation;
4764   conflict->src_left_version = src_left_version;
4765   conflict->src_right_version = src_right_version;
4766   return conflict;
4767 }
4768
4769
4770 /*** From revision_status.c ***/
4771
4772 svn_error_t *
4773 svn_wc_revision_status(svn_wc_revision_status_t **result_p,
4774                        const char *wc_path,
4775                        const char *trail_url,
4776                        svn_boolean_t committed,
4777                        svn_cancel_func_t cancel_func,
4778                        void *cancel_baton,
4779                        apr_pool_t *pool)
4780 {
4781   svn_wc_context_t *wc_ctx;
4782   const char *local_abspath;
4783
4784   SVN_ERR(svn_dirent_get_absolute(&local_abspath, wc_path, pool));
4785   SVN_ERR(svn_wc_context_create(&wc_ctx, NULL /* config */, pool, pool));
4786
4787   SVN_ERR(svn_wc_revision_status2(result_p, wc_ctx, local_abspath, trail_url,
4788                                   committed, cancel_func, cancel_baton, pool,
4789                                   pool));
4790
4791   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4792 }
4793
4794 /*** From crop.c ***/
4795 svn_error_t *
4796 svn_wc_crop_tree(svn_wc_adm_access_t *anchor,
4797                  const char *target,
4798                  svn_depth_t depth,
4799                  svn_wc_notify_func2_t notify_func,
4800                  void *notify_baton,
4801                  svn_cancel_func_t cancel_func,
4802                  void *cancel_baton,
4803                  apr_pool_t *pool)
4804 {
4805   svn_wc_context_t *wc_ctx;
4806   svn_wc__db_t *db = svn_wc__adm_get_db(anchor);
4807   const char *local_abspath;
4808
4809   local_abspath = svn_dirent_join(svn_wc__adm_access_abspath(anchor),
4810                                   target, pool);
4811
4812   SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL, db, pool));
4813
4814   if (depth == svn_depth_exclude)
4815     {
4816       SVN_ERR(svn_wc_exclude(wc_ctx,
4817                              local_abspath,
4818                              cancel_func, cancel_baton,
4819                              notify_func, notify_baton,
4820                              pool));
4821     }
4822   else
4823     {
4824       SVN_ERR(svn_wc_crop_tree2(wc_ctx,
4825                                 local_abspath,
4826                                 depth,
4827                                 cancel_func, cancel_baton,
4828                                 notify_func, notify_baton,
4829                                 pool));
4830     }
4831
4832   return svn_error_trace(svn_wc_context_destroy(wc_ctx));
4833 }
4834
4835 svn_error_t *
4836 svn_wc_move(svn_wc_context_t *wc_ctx,
4837             const char *src_abspath,
4838             const char *dst_abspath,
4839             svn_boolean_t metadata_only,
4840             svn_cancel_func_t cancel_func,
4841             void *cancel_baton,
4842             svn_wc_notify_func2_t notify_func,
4843             void *notify_baton,
4844             apr_pool_t *scratch_pool)
4845 {
4846   return svn_error_trace(svn_wc__move2(wc_ctx, src_abspath, dst_abspath,
4847                                        metadata_only,
4848                                        TRUE, /* allow_mixed_revisions */
4849                                        cancel_func, cancel_baton,
4850                                        notify_func, notify_baton,
4851                                        scratch_pool));
4852 }
4853
4854 svn_error_t *
4855 svn_wc_read_kind(svn_node_kind_t *kind,
4856                  svn_wc_context_t *wc_ctx,
4857                  const char *abspath,
4858                  svn_boolean_t show_hidden,
4859                  apr_pool_t *scratch_pool)
4860 {
4861   return svn_error_trace(
4862           svn_wc_read_kind2(kind,
4863                             wc_ctx, abspath,
4864                             TRUE /* show_deleted */,
4865                             show_hidden,
4866                             scratch_pool));
4867 }
4868
4869 svn_wc_conflict_description2_t *
4870 svn_wc__conflict_description2_dup(const svn_wc_conflict_description2_t *conflict,
4871                                   apr_pool_t *pool)
4872 {
4873   return svn_wc_conflict_description2_dup(conflict, pool);
4874 }