1251881Speter/*
2251881Speter * tree_conflicts.c: Storage of tree conflict descriptions in the WC.
3251881Speter *
4251881Speter * ====================================================================
5251881Speter *    Licensed to the Apache Software Foundation (ASF) under one
6251881Speter *    or more contributor license agreements.  See the NOTICE file
7251881Speter *    distributed with this work for additional information
8251881Speter *    regarding copyright ownership.  The ASF licenses this file
9251881Speter *    to you under the Apache License, Version 2.0 (the
10251881Speter *    "License"); you may not use this file except in compliance
11251881Speter *    with the License.  You may obtain a copy of the License at
12251881Speter *
13251881Speter *      http://www.apache.org/licenses/LICENSE-2.0
14251881Speter *
15251881Speter *    Unless required by applicable law or agreed to in writing,
16251881Speter *    software distributed under the License is distributed on an
17251881Speter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18251881Speter *    KIND, either express or implied.  See the License for the
19251881Speter *    specific language governing permissions and limitations
20251881Speter *    under the License.
21251881Speter * ====================================================================
22251881Speter */
23251881Speter
24251881Speter#include "svn_dirent_uri.h"
25251881Speter#include "svn_path.h"
26251881Speter#include "svn_types.h"
27251881Speter#include "svn_pools.h"
28251881Speter
29251881Speter#include "tree_conflicts.h"
30251881Speter#include "conflicts.h"
31251881Speter#include "wc.h"
32251881Speter
33251881Speter#include "private/svn_skel.h"
34251881Speter#include "private/svn_wc_private.h"
35251881Speter#include "private/svn_token.h"
36251881Speter
37251881Speter#include "svn_private_config.h"
38251881Speter
39251881Speter/* ### this should move to a more general location...  */
40251881Speter/* A map for svn_node_kind_t values. */
41251881Speter/* FIXME: this mapping defines a different representation of
42251881Speter          svn_node_unknown than the one defined in token-map.h */
43251881Speterstatic const svn_token_map_t node_kind_map[] =
44251881Speter{
45251881Speter  { "none", svn_node_none },
46251881Speter  { "file", svn_node_file },
47251881Speter  { "dir",  svn_node_dir },
48251881Speter  { "",     svn_node_unknown },
49289180Speter  /* ### should also map svn_node_symlink */
50251881Speter  { NULL }
51251881Speter};
52251881Speter
53251881Speter/* A map for svn_wc_operation_t values. */
54251881Speterconst svn_token_map_t svn_wc__operation_map[] =
55251881Speter{
56251881Speter  { "none",   svn_wc_operation_none },
57251881Speter  { "update", svn_wc_operation_update },
58251881Speter  { "switch", svn_wc_operation_switch },
59251881Speter  { "merge",  svn_wc_operation_merge },
60251881Speter  { NULL }
61251881Speter};
62251881Speter
63251881Speter/* A map for svn_wc_conflict_action_t values. */
64251881Speterconst svn_token_map_t svn_wc__conflict_action_map[] =
65251881Speter{
66251881Speter  { "edited",   svn_wc_conflict_action_edit },
67251881Speter  { "deleted",  svn_wc_conflict_action_delete },
68251881Speter  { "added",    svn_wc_conflict_action_add },
69251881Speter  { "replaced", svn_wc_conflict_action_replace },
70251881Speter  { NULL }
71251881Speter};
72251881Speter
73251881Speter/* A map for svn_wc_conflict_reason_t values. */
74251881Speterconst svn_token_map_t svn_wc__conflict_reason_map[] =
75251881Speter{
76251881Speter  { "edited",      svn_wc_conflict_reason_edited },
77251881Speter  { "deleted",     svn_wc_conflict_reason_deleted },
78251881Speter  { "missing",     svn_wc_conflict_reason_missing },
79251881Speter  { "obstructed",  svn_wc_conflict_reason_obstructed },
80251881Speter  { "added",       svn_wc_conflict_reason_added },
81251881Speter  { "replaced",    svn_wc_conflict_reason_replaced },
82251881Speter  { "unversioned", svn_wc_conflict_reason_unversioned },
83251881Speter  { "moved-away", svn_wc_conflict_reason_moved_away },
84251881Speter  { "moved-here", svn_wc_conflict_reason_moved_here },
85251881Speter  { NULL }
86251881Speter};
87251881Speter
88251881Speter
89251881Speter/* */
90251881Speterstatic svn_boolean_t
91251881Speteris_valid_version_info_skel(const svn_skel_t *skel)
92251881Speter{
93251881Speter  return (svn_skel__list_length(skel) == 5
94251881Speter          && svn_skel__matches_atom(skel->children, "version")
95251881Speter          && skel->children->next->is_atom
96251881Speter          && skel->children->next->next->is_atom
97251881Speter          && skel->children->next->next->next->is_atom
98251881Speter          && skel->children->next->next->next->next->is_atom);
99251881Speter}
100251881Speter
101251881Speter
102251881Speter/* */
103251881Speterstatic svn_boolean_t
104251881Speteris_valid_conflict_skel(const svn_skel_t *skel)
105251881Speter{
106251881Speter  int i;
107251881Speter
108251881Speter  if (svn_skel__list_length(skel) != 8
109251881Speter      || !svn_skel__matches_atom(skel->children, "conflict"))
110251881Speter    return FALSE;
111251881Speter
112251881Speter  /* 5 atoms ... */
113251881Speter  skel = skel->children->next;
114251881Speter  for (i = 5; i--; skel = skel->next)
115251881Speter    if (!skel->is_atom)
116251881Speter      return FALSE;
117251881Speter
118251881Speter  /* ... and 2 version info skels. */
119251881Speter  return (is_valid_version_info_skel(skel)
120251881Speter          && is_valid_version_info_skel(skel->next));
121251881Speter}
122251881Speter
123251881Speter
124251881Speter/* Parse the enumeration value in VALUE into a plain
125251881Speter * 'int', using MAP to convert from strings to enumeration values.
126251881Speter * In MAP, a null .str field marks the end of the map.
127251881Speter */
128251881Speterstatic svn_error_t *
129251881Speterread_enum_field(int *result,
130251881Speter                const svn_token_map_t *map,
131251881Speter                const svn_skel_t *skel)
132251881Speter{
133251881Speter  int value = svn_token__from_mem(map, skel->data, skel->len);
134251881Speter
135251881Speter  if (value == SVN_TOKEN_UNKNOWN)
136251881Speter    return svn_error_create(SVN_ERR_WC_CORRUPT, NULL,
137251881Speter                            _("Unknown enumeration value in tree conflict "
138251881Speter                              "description"));
139251881Speter
140251881Speter  *result = value;
141251881Speter
142251881Speter  return SVN_NO_ERROR;
143251881Speter}
144251881Speter
145251881Speter
146251881Speter/* Parse the conflict info fields from SKEL into *VERSION_INFO. */
147251881Speterstatic svn_error_t *
148251881Speterread_node_version_info(const svn_wc_conflict_version_t **version_info,
149251881Speter                       const svn_skel_t *skel,
150251881Speter                       apr_pool_t *result_pool,
151251881Speter                       apr_pool_t *scratch_pool)
152251881Speter{
153251881Speter  int n;
154251881Speter  const char *repos_root;
155251881Speter  const char *repos_relpath;
156251881Speter  svn_revnum_t peg_rev;
157251881Speter  svn_node_kind_t kind;
158251881Speter
159251881Speter  if (!is_valid_version_info_skel(skel))
160251881Speter    return svn_error_create(SVN_ERR_WC_CORRUPT, NULL,
161251881Speter                            _("Invalid version info in tree conflict "
162251881Speter                              "description"));
163251881Speter
164251881Speter  repos_root = apr_pstrmemdup(scratch_pool,
165251881Speter                              skel->children->next->data,
166251881Speter                              skel->children->next->len);
167251881Speter  if (*repos_root == '\0')
168251881Speter    {
169251881Speter      *version_info = NULL;
170251881Speter      return SVN_NO_ERROR;
171251881Speter    }
172251881Speter
173251881Speter  /* Apply the Subversion 1.7+ url canonicalization rules to a pre 1.7 url */
174251881Speter  repos_root = svn_uri_canonicalize(repos_root, result_pool);
175251881Speter
176251881Speter  peg_rev = SVN_STR_TO_REV(apr_pstrmemdup(scratch_pool,
177251881Speter                                          skel->children->next->next->data,
178251881Speter                                          skel->children->next->next->len));
179251881Speter
180251881Speter  repos_relpath = apr_pstrmemdup(result_pool,
181251881Speter                                 skel->children->next->next->next->data,
182251881Speter                                 skel->children->next->next->next->len);
183251881Speter
184251881Speter  SVN_ERR(read_enum_field(&n, node_kind_map,
185251881Speter                          skel->children->next->next->next->next));
186251881Speter  kind = (svn_node_kind_t)n;
187251881Speter
188251881Speter  *version_info = svn_wc_conflict_version_create2(repos_root,
189251881Speter                                                  NULL,
190251881Speter                                                  repos_relpath,
191251881Speter                                                  peg_rev,
192251881Speter                                                  kind,
193251881Speter                                                  result_pool);
194251881Speter
195251881Speter  return SVN_NO_ERROR;
196251881Speter}
197251881Speter
198251881Speter
199251881Spetersvn_error_t *
200251881Spetersvn_wc__deserialize_conflict(const svn_wc_conflict_description2_t **conflict,
201251881Speter                             const svn_skel_t *skel,
202251881Speter                             const char *dir_path,
203251881Speter                             apr_pool_t *result_pool,
204251881Speter                             apr_pool_t *scratch_pool)
205251881Speter{
206251881Speter  const char *victim_basename;
207251881Speter  const char *victim_abspath;
208251881Speter  svn_node_kind_t node_kind;
209251881Speter  svn_wc_operation_t operation;
210251881Speter  svn_wc_conflict_action_t action;
211251881Speter  svn_wc_conflict_reason_t reason;
212251881Speter  const svn_wc_conflict_version_t *src_left_version;
213251881Speter  const svn_wc_conflict_version_t *src_right_version;
214251881Speter  int n;
215251881Speter  svn_wc_conflict_description2_t *new_conflict;
216251881Speter
217251881Speter  if (!is_valid_conflict_skel(skel))
218251881Speter    return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL,
219251881Speter                             _("Invalid conflict info '%s' in tree conflict "
220251881Speter                               "description"),
221251881Speter                             skel ? svn_skel__unparse(skel, scratch_pool)->data
222251881Speter                                  : "(null)");
223251881Speter
224251881Speter  /* victim basename */
225251881Speter  victim_basename = apr_pstrmemdup(scratch_pool,
226251881Speter                                   skel->children->next->data,
227251881Speter                                   skel->children->next->len);
228251881Speter  if (victim_basename[0] == '\0')
229251881Speter    return svn_error_create(SVN_ERR_WC_CORRUPT, NULL,
230251881Speter                            _("Empty 'victim' field in tree conflict "
231251881Speter                              "description"));
232251881Speter
233251881Speter  /* node_kind */
234251881Speter  SVN_ERR(read_enum_field(&n, node_kind_map, skel->children->next->next));
235251881Speter  node_kind = (svn_node_kind_t)n;
236251881Speter  if (node_kind != svn_node_file && node_kind != svn_node_dir)
237251881Speter    return svn_error_create(SVN_ERR_WC_CORRUPT, NULL,
238251881Speter             _("Invalid 'node_kind' field in tree conflict description"));
239251881Speter
240251881Speter  /* operation */
241251881Speter  SVN_ERR(read_enum_field(&n, svn_wc__operation_map,
242251881Speter                          skel->children->next->next->next));
243251881Speter  operation = (svn_wc_operation_t)n;
244251881Speter
245251881Speter  SVN_ERR(svn_dirent_get_absolute(&victim_abspath,
246251881Speter                    svn_dirent_join(dir_path, victim_basename, scratch_pool),
247251881Speter                    scratch_pool));
248251881Speter
249251881Speter  /* action */
250251881Speter  SVN_ERR(read_enum_field(&n, svn_wc__conflict_action_map,
251251881Speter                          skel->children->next->next->next->next));
252251881Speter  action = n;
253251881Speter
254251881Speter  /* reason */
255251881Speter  SVN_ERR(read_enum_field(&n, svn_wc__conflict_reason_map,
256251881Speter                          skel->children->next->next->next->next->next));
257251881Speter  reason = n;
258251881Speter
259251881Speter  /* Let's just make it a bit easier on ourself here... */
260251881Speter  skel = skel->children->next->next->next->next->next->next;
261251881Speter
262251881Speter  /* src_left_version */
263251881Speter  SVN_ERR(read_node_version_info(&src_left_version, skel,
264251881Speter                                 result_pool, scratch_pool));
265251881Speter
266251881Speter  /* src_right_version */
267251881Speter  SVN_ERR(read_node_version_info(&src_right_version, skel->next,
268251881Speter                                 result_pool, scratch_pool));
269251881Speter
270251881Speter  new_conflict = svn_wc_conflict_description_create_tree2(victim_abspath,
271251881Speter    node_kind, operation, src_left_version, src_right_version,
272251881Speter    result_pool);
273251881Speter  new_conflict->action = action;
274251881Speter  new_conflict->reason = reason;
275251881Speter
276251881Speter  *conflict = new_conflict;
277251881Speter
278251881Speter  return SVN_NO_ERROR;
279251881Speter}
280251881Speter
281251881Speter
282251881Speter/* Prepend to SKEL the string corresponding to enumeration value N, as found
283251881Speter * in MAP. */
284251881Speterstatic void
285251881Speterskel_prepend_enum(svn_skel_t *skel,
286251881Speter                  const svn_token_map_t *map,
287251881Speter                  int n,
288251881Speter                  apr_pool_t *result_pool)
289251881Speter{
290251881Speter  svn_skel__prepend(svn_skel__str_atom(svn_token__to_word(map, n),
291251881Speter                                       result_pool), skel);
292251881Speter}
293251881Speter
294251881Speter
295251881Speter/* Prepend to PARENT_SKEL the several fields that represent VERSION_INFO, */
296251881Speterstatic svn_error_t *
297251881Speterprepend_version_info_skel(svn_skel_t *parent_skel,
298251881Speter                          const svn_wc_conflict_version_t *version_info,
299251881Speter                          apr_pool_t *pool)
300251881Speter{
301251881Speter  svn_skel_t *skel = svn_skel__make_empty_list(pool);
302251881Speter
303251881Speter  /* node_kind */
304251881Speter  skel_prepend_enum(skel, node_kind_map, version_info->node_kind, pool);
305251881Speter
306251881Speter  /* path_in_repos */
307251881Speter  svn_skel__prepend(svn_skel__str_atom(version_info->path_in_repos
308251881Speter                                       ? version_info->path_in_repos
309251881Speter                                       : "", pool), skel);
310251881Speter
311251881Speter  /* peg_rev */
312251881Speter  svn_skel__prepend(svn_skel__str_atom(apr_psprintf(pool, "%ld",
313251881Speter                                                    version_info->peg_rev),
314251881Speter                                       pool), skel);
315251881Speter
316251881Speter  /* repos_url */
317251881Speter  svn_skel__prepend(svn_skel__str_atom(version_info->repos_url
318251881Speter                                       ? version_info->repos_url
319251881Speter                                       : "", pool), skel);
320251881Speter
321251881Speter  svn_skel__prepend(svn_skel__str_atom("version", pool), skel);
322251881Speter
323251881Speter  SVN_ERR_ASSERT(is_valid_version_info_skel(skel));
324251881Speter
325251881Speter  svn_skel__prepend(skel, parent_skel);
326251881Speter
327251881Speter  return SVN_NO_ERROR;
328251881Speter}
329251881Speter
330251881Speter
331251881Spetersvn_error_t *
332251881Spetersvn_wc__serialize_conflict(svn_skel_t **skel,
333251881Speter                           const svn_wc_conflict_description2_t *conflict,
334251881Speter                           apr_pool_t *result_pool,
335251881Speter                           apr_pool_t *scratch_pool)
336251881Speter{
337251881Speter  /* A conflict version struct with all fields null/invalid. */
338251881Speter  static const svn_wc_conflict_version_t null_version = {
339251881Speter    NULL, SVN_INVALID_REVNUM, NULL, svn_node_unknown };
340251881Speter  svn_skel_t *c_skel = svn_skel__make_empty_list(result_pool);
341251881Speter  const char *victim_basename;
342251881Speter
343251881Speter  /* src_right_version */
344251881Speter  if (conflict->src_right_version)
345251881Speter    SVN_ERR(prepend_version_info_skel(c_skel, conflict->src_right_version,
346251881Speter                                      result_pool));
347251881Speter  else
348251881Speter    SVN_ERR(prepend_version_info_skel(c_skel, &null_version, result_pool));
349251881Speter
350251881Speter  /* src_left_version */
351251881Speter  if (conflict->src_left_version)
352251881Speter    SVN_ERR(prepend_version_info_skel(c_skel, conflict->src_left_version,
353251881Speter                                      result_pool));
354251881Speter  else
355251881Speter    SVN_ERR(prepend_version_info_skel(c_skel, &null_version, result_pool));
356251881Speter
357289180Speter  /* local change */
358289180Speter  skel_prepend_enum(c_skel, svn_wc__conflict_reason_map,
359289180Speter                    conflict->reason, result_pool);
360251881Speter
361289180Speter  /* incoming change */
362289180Speter  skel_prepend_enum(c_skel, svn_wc__conflict_action_map,
363289180Speter                    conflict->action, result_pool);
364251881Speter
365251881Speter  /* operation */
366251881Speter  skel_prepend_enum(c_skel, svn_wc__operation_map, conflict->operation,
367251881Speter                    result_pool);
368251881Speter
369251881Speter  /* node_kind */
370251881Speter  SVN_ERR_ASSERT(conflict->node_kind == svn_node_dir
371289180Speter                 || conflict->node_kind == svn_node_file
372289180Speter                 || conflict->node_kind == svn_node_none);
373289180Speter  skel_prepend_enum(c_skel, node_kind_map, conflict->node_kind,
374289180Speter                    result_pool);
375251881Speter
376251881Speter  /* Victim path (escaping separator chars). */
377251881Speter  victim_basename = svn_dirent_basename(conflict->local_abspath, result_pool);
378251881Speter  SVN_ERR_ASSERT(victim_basename[0]);
379251881Speter  svn_skel__prepend(svn_skel__str_atom(victim_basename, result_pool), c_skel);
380251881Speter
381251881Speter  svn_skel__prepend(svn_skel__str_atom("conflict", result_pool), c_skel);
382251881Speter
383251881Speter  SVN_ERR_ASSERT(is_valid_conflict_skel(c_skel));
384251881Speter
385251881Speter  *skel = c_skel;
386251881Speter
387251881Speter  return SVN_NO_ERROR;
388251881Speter}
389251881Speter
390251881Speter
391251881Spetersvn_error_t *
392251881Spetersvn_wc__del_tree_conflict(svn_wc_context_t *wc_ctx,
393251881Speter                          const char *victim_abspath,
394251881Speter                          apr_pool_t *scratch_pool)
395251881Speter{
396251881Speter  SVN_ERR_ASSERT(svn_dirent_is_absolute(victim_abspath));
397251881Speter
398251881Speter  SVN_ERR(svn_wc__db_op_mark_resolved(wc_ctx->db, victim_abspath,
399251881Speter                                      FALSE, FALSE, TRUE, NULL,
400251881Speter                                      scratch_pool));
401251881Speter
402251881Speter   return SVN_NO_ERROR;
403251881Speter }
404251881Speter
405251881Spetersvn_error_t *
406251881Spetersvn_wc__add_tree_conflict(svn_wc_context_t *wc_ctx,
407251881Speter                          const svn_wc_conflict_description2_t *conflict,
408251881Speter                          apr_pool_t *scratch_pool)
409251881Speter{
410251881Speter  svn_boolean_t existing_conflict;
411251881Speter  svn_skel_t *conflict_skel;
412251881Speter  svn_error_t *err;
413251881Speter
414251881Speter  SVN_ERR_ASSERT(conflict != NULL);
415289180Speter  SVN_ERR_ASSERT(conflict->operation == svn_wc_operation_merge ||
416289180Speter                 (conflict->reason != svn_wc_conflict_reason_moved_away &&
417289180Speter                  conflict->reason != svn_wc_conflict_reason_moved_here));
418251881Speter
419251881Speter  /* Re-adding an existing tree conflict victim is an error. */
420251881Speter  err = svn_wc__internal_conflicted_p(NULL, NULL, &existing_conflict,
421251881Speter                                      wc_ctx->db, conflict->local_abspath,
422251881Speter                                      scratch_pool);
423251881Speter  if (err)
424251881Speter    {
425251881Speter      if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
426251881Speter        return svn_error_trace(err);
427251881Speter
428251881Speter      svn_error_clear(err);
429251881Speter    }
430251881Speter  else if (existing_conflict)
431251881Speter    return svn_error_createf(SVN_ERR_WC_PATH_UNEXPECTED_STATUS, NULL,
432251881Speter                             _("Attempt to add tree conflict that already "
433251881Speter                               "exists at '%s'"),
434251881Speter                             svn_dirent_local_style(conflict->local_abspath,
435251881Speter                                                    scratch_pool));
436251881Speter  else if (!conflict)
437251881Speter    return SVN_NO_ERROR;
438251881Speter
439251881Speter  conflict_skel = svn_wc__conflict_skel_create(scratch_pool);
440251881Speter
441251881Speter  SVN_ERR(svn_wc__conflict_skel_add_tree_conflict(conflict_skel, wc_ctx->db,
442251881Speter                                                  conflict->local_abspath,
443251881Speter                                                  conflict->reason,
444251881Speter                                                  conflict->action,
445362181Sdim                                                  NULL, NULL,
446251881Speter                                                  scratch_pool, scratch_pool));
447251881Speter
448289180Speter  switch (conflict->operation)
449251881Speter    {
450251881Speter      case svn_wc_operation_update:
451251881Speter      default:
452251881Speter        SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict_skel,
453251881Speter                                                    conflict->src_left_version,
454251881Speter                                                    conflict->src_right_version,
455251881Speter                                                    scratch_pool, scratch_pool));
456251881Speter        break;
457251881Speter      case svn_wc_operation_switch:
458251881Speter        SVN_ERR(svn_wc__conflict_skel_set_op_switch(conflict_skel,
459251881Speter                                                    conflict->src_left_version,
460251881Speter                                                    conflict->src_right_version,
461251881Speter                                                    scratch_pool, scratch_pool));
462251881Speter        break;
463251881Speter      case svn_wc_operation_merge:
464251881Speter        SVN_ERR(svn_wc__conflict_skel_set_op_merge(conflict_skel,
465251881Speter                                                   conflict->src_left_version,
466251881Speter                                                   conflict->src_right_version,
467251881Speter                                                   scratch_pool, scratch_pool));
468251881Speter        break;
469251881Speter    }
470251881Speter
471251881Speter  return svn_error_trace(
472251881Speter                svn_wc__db_op_mark_conflict(wc_ctx->db, conflict->local_abspath,
473251881Speter                                            conflict_skel, NULL, scratch_pool));
474251881Speter}
475251881Speter
476251881Speter
477251881Spetersvn_error_t *
478251881Spetersvn_wc__get_tree_conflict(const svn_wc_conflict_description2_t **tree_conflict,
479251881Speter                          svn_wc_context_t *wc_ctx,
480251881Speter                          const char *local_abspath,
481251881Speter                          apr_pool_t *result_pool,
482251881Speter                          apr_pool_t *scratch_pool)
483251881Speter{
484251881Speter  const apr_array_header_t *conflicts;
485251881Speter  int i;
486251881Speter  SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
487251881Speter
488289180Speter  SVN_ERR(svn_wc__read_conflicts(&conflicts, NULL,
489289180Speter                                 wc_ctx->db, local_abspath,
490289180Speter                                 FALSE /* temp files */,
491289180Speter                                 TRUE /* only tree conflicts */,
492251881Speter                                 scratch_pool, scratch_pool));
493251881Speter
494251881Speter  if (!conflicts || conflicts->nelts == 0)
495251881Speter    {
496251881Speter      *tree_conflict = NULL;
497251881Speter      return SVN_NO_ERROR;
498251881Speter    }
499251881Speter
500251881Speter  for (i = 0; i < conflicts->nelts; i++)
501251881Speter    {
502251881Speter      const svn_wc_conflict_description2_t *desc;
503251881Speter
504251881Speter      desc = APR_ARRAY_IDX(conflicts, i, svn_wc_conflict_description2_t *);
505251881Speter
506251881Speter      if (desc->kind == svn_wc_conflict_kind_tree)
507251881Speter        {
508289180Speter          *tree_conflict = svn_wc_conflict_description2_dup(desc, result_pool);
509251881Speter          return SVN_NO_ERROR;
510251881Speter        }
511251881Speter    }
512251881Speter
513251881Speter  *tree_conflict = NULL;
514251881Speter  return SVN_NO_ERROR;
515251881Speter}
516251881Speter
517