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