]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - contrib/subversion/subversion/libsvn_client/merge.c
- Copy stable/10@296371 to releng/10.3 in preparation for 10.3-RC1
[FreeBSD/releng/10.3.git] / contrib / subversion / subversion / libsvn_client / merge.c
1 /*
2  * merge.c: merging
3  *
4  * ====================================================================
5  *    Licensed to the Apache Software Foundation (ASF) under one
6  *    or more contributor license agreements.  See the NOTICE file
7  *    distributed with this work for additional information
8  *    regarding copyright ownership.  The ASF licenses this file
9  *    to you under the Apache License, Version 2.0 (the
10  *    "License"); you may not use this file except in compliance
11  *    with the License.  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  *    Unless required by applicable law or agreed to in writing,
16  *    software distributed under the License is distributed on an
17  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18  *    KIND, either express or implied.  See the License for the
19  *    specific language governing permissions and limitations
20  *    under the License.
21  * ====================================================================
22  */
23
24 /* ==================================================================== */
25
26
27 \f
28 /*** Includes ***/
29
30 #include <assert.h>
31 #include <apr_strings.h>
32 #include <apr_tables.h>
33 #include <apr_hash.h>
34 #include "svn_types.h"
35 #include "svn_hash.h"
36 #include "svn_wc.h"
37 #include "svn_delta.h"
38 #include "svn_diff.h"
39 #include "svn_mergeinfo.h"
40 #include "svn_client.h"
41 #include "svn_string.h"
42 #include "svn_error.h"
43 #include "svn_dirent_uri.h"
44 #include "svn_path.h"
45 #include "svn_io.h"
46 #include "svn_utf.h"
47 #include "svn_pools.h"
48 #include "svn_config.h"
49 #include "svn_props.h"
50 #include "svn_time.h"
51 #include "svn_sorts.h"
52 #include "svn_subst.h"
53 #include "svn_ra.h"
54 #include "client.h"
55 #include "mergeinfo.h"
56
57 #include "private/svn_opt_private.h"
58 #include "private/svn_wc_private.h"
59 #include "private/svn_mergeinfo_private.h"
60 #include "private/svn_fspath.h"
61 #include "private/svn_ra_private.h"
62 #include "private/svn_client_private.h"
63 #include "private/svn_subr_private.h"
64
65 #include "svn_private_config.h"
66
67
68 /*-----------------------------------------------------------------------*/
69 \f
70 /* MERGEINFO MERGE SOURCE NORMALIZATION
71  *
72  * Nearly any helper function herein that accepts two URL/revision
73  * pairs (or equivalent struct merge_source_t) expects one of two things
74  * to be true:
75  *
76  *    1.  that mergeinfo is not being recorded at all for this
77  *        operation, or
78  *
79  *    2.  that the pairs represent two locations along a single line
80  *        of version history such that there are no copies in the
81  *        history of the object between the locations when treating
82  *        the oldest of the two locations as non-inclusive.  In other
83  *        words, if there is a copy at all between them, there is only
84  *        one copy and its source was the oldest of the two locations.
85  *
86  * We use svn_ra_get_location_segments() to split a given range of
87  * revisions across an object's history into several which obey these
88  * rules.  For example, an extract from the log of Subversion's own
89  * /subversion/tags/1.4.5 directory shows the following copies between
90  * r859500 and r866500 (omitting the '/subversion' prefix for clarity):
91  *
92  *    r859598:
93  *      A /branches/1.4.x  (from /trunk:859597)
94  *
95  *    r865417:
96  *      A /tags/1.4.4      (from /branches/1.4.x:865262)
97  *    # Notice that this copy leaves a gap between 865262 and 865417.
98  *
99  *    r866420:
100  *      A /branches/1.4.5  (from /tags/1.4.4:866419)
101  *
102  *    r866425:
103  *      D /branches/1.4.5
104  *      A /tags/1.4.5      (from /branches/1.4.5:866424)
105  *
106  * In graphical form:
107  *
108  *                859500 859597 865262        866419 866424 866500
109  *                  .      .      .             .      .      .
110  *    trunk       ------------------------------------------------
111  *                         \      .             .      .
112  *    branches/1.4.x        A-------------------------------------
113  *                          .     \______       .      .
114  *                          .            \      .      .
115  *    tags/1.4.4            .             A-----------------------
116  *                          .             .     \      .
117  *    branches/1.4.5        .             .      A------D
118  *                          .             .      .     \.
119  *    tags/1.4.5            .             .      .      A---------
120  *                          .             .      .      .
121  *                       859598        865417 866420 866425
122  *
123  * A merge of the difference between r859500 and r866500 of this directory
124  * gets split into sequential merges of the following location pairs.
125  *
126  *                859500 859597 865262 865416 866419 866424 866500
127  *                  .      .      .      .      .      .      .
128  *    trunk         (======]      .      .      .      .      .
129  *                                .      .      .      .      .
130  *    trunk                (      .      .      .      .      .
131  *    branches/1.4.x        ======]      .      .      .      .
132  *                                       .      .      .      .
133  *    branches/1.4.x              (      .      .      .      .
134  *    tags/1.4.4                   =============]      .      .
135  *    implicit_src_gap            (======]      .      .      .
136  *                                              .      .      .
137  *    tags/1.4.4                                (      .      .
138  *    branches/1.4.5                             ======]      .
139  *                                                     .      .
140  *    branches/1.4.5                                   (      .
141  *    tags/1.4.5                                        ======]
142  *
143  * which are represented in merge_source_t as:
144  *
145  *    [/trunk:859500, /trunk:859597]
146  *    (recorded in svn:mergeinfo as /trunk:859501-859597)
147  *
148  *    [/trunk:859597, /branches/1.4.x:865262]
149  *    (recorded in svn:mergeinfo as /branches/1.4.x:859598-865262)
150  *
151  *    [/branches/1.4.x:865262, /tags/1.4.4@866419]
152  *    (recorded in svn:mergeinfo as /tags/1.4.4:865263-866419)
153  *    (and there is a gap, the revision range [865262, 865416])
154  *
155  *    [/tags/1.4.4@866419, /branches/1.4.5@866424]
156  *    (recorded in svn:mergeinfo as /branches/1.4.5:866420-866424)
157  *
158  *    [/branches/1.4.5@866424, /tags/1.4.5@866500]
159  *    (recorded in svn:mergeinfo as /tags/1.4.5:866425-866500)
160  *
161  * Our helper functions would then operate on one of these location
162  * pairs at a time.
163  */
164
165 /* WHICH SVN_CLIENT_MERGE* API DO I WANT?
166  *
167  * libsvn_client has three public merge APIs; they are all wrappers
168  * around the do_merge engine.  Which one to use depends on the number
169  * of URLs passed as arguments and whether or not specific merge
170  * ranges (-c/-r) are specified.
171  *
172  *                 1 URL                        2 URLs
173  * +----+--------------------------------+---------------------+
174  * | -c |       mergeinfo-driven         |                     |
175  * | or |        cherrypicking           |                     |
176  * | -r |    (svn_client_merge_peg)      |                     |
177  * |----+--------------------------------+                     |
178  * |    |       mergeinfo-driven         |     unsupported     |
179  * |    |  'cherry harvest', i.e. merge  |                     |
180  * |    |  all revisions from URL that   |                     |
181  * | no |  have not already been merged  |                     |
182  * | -c |    (svn_client_merge_peg)      |                     |
183  * | or +--------------------------------+---------------------+
184  * | -r |      mergeinfo-driven          |   mergeinfo-writing |
185  * |    |        whole-branch            |    diff-and-apply   |
186  * |    |       heuristic merge          |  (svn_client_merge) |
187  * |    | (svn_client_merge_reintegrate) |                     |
188  * +----+--------------------------------+---------------------+
189  *
190  *
191  */
192
193 /* THE CHILDREN_WITH_MERGEINFO ARRAY
194  *
195  * Many of the helper functions in this file pass around an
196  * apr_array_header_t *CHILDREN_WITH_MERGEINFO.  This is a depth first
197  * sorted array filled with svn_client__merge_path_t * describing the
198  * merge target and any of its subtrees which have explicit mergeinfo
199  * or otherwise need special attention during a merge.
200  *
201  * During mergeinfo unaware merges, CHILDREN_WITH_MERGEINFO contains
202  * contains only one element (added by do_mergeinfo_unaware_dir_merge)
203  * describing a contiguous range to be merged to the WC merge target.
204  *
205  * During mergeinfo aware merges CHILDREN_WITH_MERGEINFO is created
206  * by get_mergeinfo_paths() and outside of that function and its helpers
207  * should always meet the criteria dictated in get_mergeinfo_paths()'s doc
208  * string.  The elements of CHILDREN_WITH_MERGEINFO should never be NULL.
209  *
210  * For clarification on mergeinfo aware vs. mergeinfo unaware merges, see
211  * the doc string for HONOR_MERGEINFO().
212  */
213
214
215 /*-----------------------------------------------------------------------*/
216 \f
217 /*** Repos-Diff Editor Callbacks ***/
218
219 /* */
220 typedef struct merge_source_t
221 {
222   /* "left" side URL and revision (inclusive iff youngest) */
223   const svn_client__pathrev_t *loc1;
224
225   /* "right" side URL and revision (inclusive iff youngest) */
226   const svn_client__pathrev_t *loc2;
227
228   /* True iff LOC1 is an ancestor of LOC2 or vice-versa (history-wise). */
229   svn_boolean_t ancestral;
230 } merge_source_t;
231
232 /* Description of the merge target root node (a WC working node) */
233 typedef struct merge_target_t
234 {
235   /* Absolute path to the WC node */
236   const char *abspath;
237
238   /* The repository location of the base node of the target WC.  If the node
239    * is locally added, then URL & REV are NULL & SVN_INVALID_REVNUM.
240    * REPOS_ROOT_URL and REPOS_UUID are always valid. */
241   svn_client__pathrev_t loc;
242
243 } merge_target_t;
244
245 typedef struct merge_cmd_baton_t {
246   svn_boolean_t force_delete;         /* Delete a file/dir even if modified */
247   svn_boolean_t dry_run;
248   svn_boolean_t record_only;          /* Whether to merge only mergeinfo
249                                          differences. */
250   svn_boolean_t same_repos;           /* Whether the merge source repository
251                                          is the same repository as the
252                                          target.  Defaults to FALSE if DRY_RUN
253                                          is TRUE.*/
254   svn_boolean_t mergeinfo_capable;    /* Whether the merge source server
255                                          is capable of Merge Tracking. */
256   svn_boolean_t ignore_mergeinfo;     /* Don't honor mergeinfo; see
257                                          doc string of do_merge().  FALSE if
258                                          MERGE_SOURCE->ancestral is FALSE. */
259   svn_boolean_t diff_ignore_ancestry; /* Diff unrelated nodes as if related; see
260                                          doc string of do_merge().  FALSE if
261                                          MERGE_SOURCE->ancestral is FALSE. */
262   svn_boolean_t reintegrate_merge;    /* Whether this is a --reintegrate
263                                          merge or not. */
264   const merge_target_t *target;       /* Description of merge target node */
265
266   /* The left and right URLs and revs.  The value of this field changes to
267      reflect the merge_source_t *currently* being merged by do_merge(). */
268   merge_source_t merge_source;
269
270   /* Rangelist containing single range which describes the gap, if any,
271      in the natural history of the merge source currently being processed.
272      See http://subversion.tigris.org/issues/show_bug.cgi?id=3432.
273      Updated during each call to do_directory_merge().  May be NULL if there
274      is no gap. */
275   svn_rangelist_t *implicit_src_gap;
276
277   svn_client_ctx_t *ctx;              /* Client context for callbacks, etc. */
278
279   /* The list of any paths which remained in conflict after a
280      resolution attempt was made.  We track this in-memory, rather
281      than just using WC entry state, since the latter doesn't help us
282      when in dry_run mode.
283      ### And because we only want to resolve conflicts that were
284          generated by this merge, not pre-existing ones? */
285   apr_hash_t *conflicted_paths;
286
287   /* A list of absolute paths which had no explicit mergeinfo prior to the
288      merge but got explicit mergeinfo added by the merge.  This is populated
289      by merge_change_props() and is allocated in POOL so it is subject to the
290      lifetime limitations of POOL.  Is NULL if no paths are found which
291      meet the criteria or DRY_RUN is true. */
292   apr_hash_t *paths_with_new_mergeinfo;
293
294   /* A list of absolute paths whose mergeinfo doesn't need updating after
295      the merge. This can be caused by the removal of mergeinfo by the merge
296      or by deleting the node itself.  This is populated by merge_change_props()
297      and the delete callbacks and is allocated in POOL so it is subject to the
298      lifetime limitations of POOL.  Is NULL if no paths are found which
299      meet the criteria or DRY_RUN is true. */
300   apr_hash_t *paths_with_deleted_mergeinfo;
301
302   /* The list of absolute skipped paths, which should be examined and
303      cleared after each invocation of the callback.  The paths
304      are absolute.  Is NULL if MERGE_B->MERGE_SOURCE->ancestral and
305      MERGE_B->REINTEGRATE_MERGE are both false. */
306   apr_hash_t *skipped_abspaths;
307
308   /* The list of absolute merged paths.  Unused if MERGE_B->MERGE_SOURCE->ancestral
309      and MERGE_B->REINTEGRATE_MERGE are both false. */
310   apr_hash_t *merged_abspaths;
311
312   /* A hash of (const char *) absolute WC paths mapped to the same which
313      represent the roots of subtrees added by the merge. */
314   apr_hash_t *added_abspaths;
315
316   /* A list of tree conflict victim absolute paths which may be NULL. */
317   apr_hash_t *tree_conflicted_abspaths;
318
319   /* The diff3_cmd in ctx->config, if any, else null.  We could just
320      extract this as needed, but since more than one caller uses it,
321      we just set it up when this baton is created. */
322   const char *diff3_cmd;
323   const apr_array_header_t *merge_options;
324
325   /* Array of file extension patterns to preserve as extensions in
326      generated conflict files. */
327   const apr_array_header_t *ext_patterns;
328
329   /* RA sessions used throughout a merge operation.  Opened/re-parented
330      as needed.
331
332      NOTE: During the actual merge editor drive, RA_SESSION1 is used
333      for the primary editing and RA_SESSION2 for fetching additional
334      information -- as necessary -- from the repository.  So during
335      this phase of the merge, you *must not* reparent RA_SESSION1; use
336      (temporarily reparenting if you must) RA_SESSION2 instead.  */
337   svn_ra_session_t *ra_session1;
338   svn_ra_session_t *ra_session2;
339
340   /* During the merge, *USE_SLEEP is set to TRUE if a sleep will be required
341      afterwards to ensure timestamp integrity, or unchanged if not. */
342   svn_boolean_t *use_sleep;
343
344   /* Pool which has a lifetime limited to one iteration over a given
345      merge source, i.e. it is cleared on every call to do_directory_merge()
346      or do_file_merge() in do_merge(). */
347   apr_pool_t *pool;
348
349
350   /* State for notify_merge_begin() */
351   struct notify_begin_state_t
352   {
353     /* Cache of which abspath was last notified. */
354     const char *last_abspath;
355
356     /* Reference to the one-and-only CHILDREN_WITH_MERGEINFO (see global
357        comment) or a similar list for single-file-merges */
358     const apr_array_header_t *nodes_with_mergeinfo;
359   } notify_begin;
360
361 } merge_cmd_baton_t;
362
363
364 /* Return TRUE iff we should be taking account of mergeinfo in deciding what
365    changes to merge, for the merge described by MERGE_B.  Specifically, that
366    is if the merge source server is capable of merge tracking, the left-side
367    merge source is an ancestor of the right-side (or vice-versa), the merge
368    source is in the same repository as the merge target, and we are not
369    ignoring mergeinfo. */
370 #define HONOR_MERGEINFO(merge_b) ((merge_b)->mergeinfo_capable      \
371                                   && (merge_b)->merge_source.ancestral  \
372                                   && (merge_b)->same_repos          \
373                                   && (! (merge_b)->ignore_mergeinfo))
374
375
376 /* Return TRUE iff we should be recording mergeinfo for the merge described
377    by MERGE_B.  Specifically, that is if we are honoring mergeinfo and the
378    merge is not a dry run.  */
379 #define RECORD_MERGEINFO(merge_b) (HONOR_MERGEINFO(merge_b) \
380                                    && !(merge_b)->dry_run)
381
382
383 /*-----------------------------------------------------------------------*/
384 \f
385 /*** Utilities ***/
386
387 /* Return TRUE iff the session URL of RA_SESSION is equal to URL.  Useful in
388  * asserting preconditions. */
389 static svn_boolean_t
390 session_url_is(svn_ra_session_t *ra_session,
391                const char *url,
392                apr_pool_t *scratch_pool)
393 {
394   const char *session_url;
395   svn_error_t *err
396     = svn_ra_get_session_url(ra_session, &session_url, scratch_pool);
397
398   SVN_ERR_ASSERT_NO_RETURN(! err);
399   return strcmp(url, session_url) == 0;
400 }
401
402 /* Return a new merge_source_t structure, allocated in RESULT_POOL,
403  * initialized with deep copies of LOC1 and LOC2 and ANCESTRAL. */
404 static merge_source_t *
405 merge_source_create(const svn_client__pathrev_t *loc1,
406                     const svn_client__pathrev_t *loc2,
407                     svn_boolean_t ancestral,
408                     apr_pool_t *result_pool)
409 {
410   merge_source_t *s
411     = apr_palloc(result_pool, sizeof(*s));
412
413   s->loc1 = svn_client__pathrev_dup(loc1, result_pool);
414   s->loc2 = svn_client__pathrev_dup(loc2, result_pool);
415   s->ancestral = ancestral;
416   return s;
417 }
418
419 /* Return a deep copy of SOURCE, allocated in RESULT_POOL. */
420 static merge_source_t *
421 merge_source_dup(const merge_source_t *source,
422                  apr_pool_t *result_pool)
423 {
424   merge_source_t *s = apr_palloc(result_pool, sizeof(*s));
425
426   s->loc1 = svn_client__pathrev_dup(source->loc1, result_pool);
427   s->loc2 = svn_client__pathrev_dup(source->loc2, result_pool);
428   s->ancestral = source->ancestral;
429   return s;
430 }
431
432 /* Return SVN_ERR_UNSUPPORTED_FEATURE if URL is not inside the repository
433    of LOCAL_ABSPATH.  Use SCRATCH_POOL for temporary allocations. */
434 static svn_error_t *
435 check_repos_match(const merge_target_t *target,
436                   const char *local_abspath,
437                   const char *url,
438                   apr_pool_t *scratch_pool)
439 {
440   if (!svn_uri__is_ancestor(target->loc.repos_root_url, url))
441     return svn_error_createf(
442         SVN_ERR_UNSUPPORTED_FEATURE, NULL,
443          _("URL '%s' of '%s' is not in repository '%s'"),
444          url, svn_dirent_local_style(local_abspath, scratch_pool),
445          target->loc.repos_root_url);
446
447   return SVN_NO_ERROR;
448 }
449
450 /* Return TRUE iff the repository of LOCATION1 is the same as
451  * that of LOCATION2.  If STRICT_URLS is true, the URLs must
452  * match (and the UUIDs, just to be sure), otherwise just the UUIDs must
453  * match and the URLs can differ (a common case is http versus https). */
454 static svn_boolean_t
455 is_same_repos(const svn_client__pathrev_t *location1,
456               const svn_client__pathrev_t *location2,
457               svn_boolean_t strict_urls)
458 {
459   if (strict_urls)
460     return (strcmp(location1->repos_root_url, location2->repos_root_url) == 0
461             && strcmp(location1->repos_uuid, location2->repos_uuid) == 0);
462   else
463     return (strcmp(location1->repos_uuid, location2->repos_uuid) == 0);
464 }
465
466 /* If the repository identified of LOCATION1 is not the same as that
467  * of LOCATION2, throw a SVN_ERR_CLIENT_UNRELATED_RESOURCES
468  * error mentioning PATH1 and PATH2. For STRICT_URLS, see is_same_repos().
469  */
470 static svn_error_t *
471 check_same_repos(const svn_client__pathrev_t *location1,
472                  const char *path1,
473                  const svn_client__pathrev_t *location2,
474                  const char *path2,
475                  svn_boolean_t strict_urls,
476                  apr_pool_t *scratch_pool)
477 {
478   if (! is_same_repos(location1, location2, strict_urls))
479     return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
480                              _("'%s' must be from the same repository as "
481                                "'%s'"), path1, path2);
482   return SVN_NO_ERROR;
483 }
484
485 /* Store LOCAL_ABSPATH in PATH_HASH after duplicating it into the pool
486    containing PATH_HASH. */
487 static APR_INLINE void
488 store_path(apr_hash_t *path_hash, const char *local_abspath)
489 {
490   const char *dup_path = apr_pstrdup(apr_hash_pool_get(path_hash),
491                                      local_abspath);
492
493   svn_hash_sets(path_hash, dup_path, dup_path);
494 }
495
496 /* Store LOCAL_ABSPATH in *PATH_HASH_P after duplicating it into the pool
497    containing *PATH_HASH_P.  If *PATH_HASH_P is NULL, then first set
498    *PATH_HASH_P to a new hash allocated from POOL.  */
499 static APR_INLINE void
500 alloc_and_store_path(apr_hash_t **path_hash_p,
501                      const char *local_abspath,
502                      apr_pool_t *pool)
503 {
504   if (! *path_hash_p)
505     *path_hash_p = apr_hash_make(pool);
506   store_path(*path_hash_p, local_abspath);
507 }
508
509 /* Return whether any WC path was put in conflict by the merge
510    operation corresponding to MERGE_B. */
511 static APR_INLINE svn_boolean_t
512 is_path_conflicted_by_merge(merge_cmd_baton_t *merge_b)
513 {
514   return (merge_b->conflicted_paths &&
515           apr_hash_count(merge_b->conflicted_paths) > 0);
516 }
517
518 /* Return a state indicating whether the WC metadata matches the
519  * node kind on disk of the local path LOCAL_ABSPATH.
520  * Use MERGE_B to determine the dry-run details; particularly, if a dry run
521  * noted that it deleted this path, assume matching node kinds (as if both
522  * kinds were svn_node_none).
523  *
524  *   - Return svn_wc_notify_state_inapplicable if the node kind matches.
525  *   - Return 'obstructed' if there is a node on disk where none or a
526  *     different kind is expected, or if the disk node cannot be read.
527  *   - Return 'missing' if there is no node on disk but one is expected.
528  *     Also return 'missing' for server-excluded nodes (not here due to
529  *     authz or other reasons determined by the server).
530  *
531  * Optionally return a bit more info for interested users.
532  **/
533 static svn_error_t *
534 perform_obstruction_check(svn_wc_notify_state_t *obstruction_state,
535                           svn_boolean_t *deleted,
536                           svn_boolean_t *excluded,
537                           svn_node_kind_t *kind,
538                           svn_depth_t *parent_depth,
539                           const merge_cmd_baton_t *merge_b,
540                           const char *local_abspath,
541                           apr_pool_t *scratch_pool)
542 {
543   svn_wc_context_t *wc_ctx = merge_b->ctx->wc_ctx;
544   svn_node_kind_t wc_kind;
545   svn_boolean_t check_root;
546
547   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
548
549   *obstruction_state = svn_wc_notify_state_inapplicable;
550
551   if (deleted)
552     *deleted = FALSE;
553   if (kind)
554     *kind = svn_node_none;
555
556   if (kind == NULL)
557     kind = &wc_kind;
558
559   check_root = ! strcmp(local_abspath, merge_b->target->abspath);
560
561   SVN_ERR(svn_wc__check_for_obstructions(obstruction_state,
562                                          kind,
563                                          deleted,
564                                          excluded,
565                                          parent_depth,
566                                          wc_ctx, local_abspath,
567                                          check_root,
568                                          scratch_pool));
569   return SVN_NO_ERROR;
570 }
571
572 /* Create *LEFT and *RIGHT conflict versions for conflict victim
573  * at VICTIM_ABSPATH, with kind NODE_KIND, using information obtained
574  * from MERGE_SOURCE and TARGET.
575  * Allocate returned conflict versions in RESULT_POOL. */
576 static svn_error_t *
577 make_conflict_versions(const svn_wc_conflict_version_t **left,
578                        const svn_wc_conflict_version_t **right,
579                        const char *victim_abspath,
580                        svn_node_kind_t node_kind,
581                        const merge_source_t *merge_source,
582                        const merge_target_t *target,
583                        apr_pool_t *result_pool,
584                        apr_pool_t *scratch_pool)
585 {
586   const char *child = svn_dirent_skip_ancestor(target->abspath,
587                                                victim_abspath);
588   const char *left_relpath, *right_relpath;
589
590   SVN_ERR_ASSERT(child != NULL);
591   left_relpath = svn_client__pathrev_relpath(merge_source->loc1,
592                                              scratch_pool);
593   right_relpath = svn_client__pathrev_relpath(merge_source->loc2,
594                                               scratch_pool);
595
596   *left = svn_wc_conflict_version_create2(
597             merge_source->loc1->repos_root_url,
598             merge_source->loc1->repos_uuid,
599             svn_relpath_join(left_relpath, child, scratch_pool),
600             merge_source->loc1->rev, node_kind, result_pool);
601
602   *right = svn_wc_conflict_version_create2(
603              merge_source->loc2->repos_root_url,
604              merge_source->loc2->repos_uuid,
605              svn_relpath_join(right_relpath, child, scratch_pool),
606              merge_source->loc2->rev, node_kind, result_pool);
607
608   return SVN_NO_ERROR;
609 }
610
611 /* Helper for filter_self_referential_mergeinfo()
612
613    *MERGEINFO is a non-empty, non-null collection of mergeinfo.
614
615    Remove all mergeinfo from *MERGEINFO that describes revision ranges
616    greater than REVISION.  Put a copy of any removed mergeinfo, allocated
617    in POOL, into *YOUNGER_MERGEINFO.
618
619    If no mergeinfo is removed from *MERGEINFO then *YOUNGER_MERGEINFO is set
620    to NULL.  If all mergeinfo is removed from *MERGEINFO then *MERGEINFO is
621    set to NULL.
622    */
623 static svn_error_t*
624 split_mergeinfo_on_revision(svn_mergeinfo_t *younger_mergeinfo,
625                             svn_mergeinfo_t *mergeinfo,
626                             svn_revnum_t revision,
627                             apr_pool_t *pool)
628 {
629   apr_hash_index_t *hi;
630   apr_pool_t *iterpool = svn_pool_create(pool);
631
632   *younger_mergeinfo = NULL;
633   for (hi = apr_hash_first(pool, *mergeinfo); hi; hi = apr_hash_next(hi))
634     {
635       int i;
636       const char *merge_source_path = svn__apr_hash_index_key(hi);
637       svn_rangelist_t *rangelist = svn__apr_hash_index_val(hi);
638
639       svn_pool_clear(iterpool);
640
641       for (i = 0; i < rangelist->nelts; i++)
642         {
643           svn_merge_range_t *range =
644             APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
645           if (range->end <= revision)
646             {
647               /* This entirely of this range is as old or older than
648                  REVISION, so leave it in *MERGEINFO. */
649               continue;
650             }
651           else
652             {
653               /* Since the rangelists in svn_mergeinfo_t's are sorted in
654                  increasing order we know that part or all of *this* range
655                  and *all* of the remaining ranges in *RANGELIST are younger
656                  than REVISION.  Remove the younger rangelists from
657                  *MERGEINFO and put them in *YOUNGER_MERGEINFO. */
658               int j;
659               svn_rangelist_t *younger_rangelist =
660                 apr_array_make(pool, 1, sizeof(svn_merge_range_t *));
661
662               for (j = i; j < rangelist->nelts; j++)
663                 {
664                   svn_merge_range_t *younger_range = svn_merge_range_dup(
665                     APR_ARRAY_IDX(rangelist, j, svn_merge_range_t *), pool);
666
667                   /* REVISION might intersect with the first range where
668                      range->end > REVISION.  If that is the case then split
669                      the current range into two, putting the younger half
670                      into *YOUNGER_MERGEINFO and leaving the older half in
671                      *MERGEINFO. */
672                   if (j == i && range->start + 1 <= revision)
673                     younger_range->start = range->end = revision;
674
675                   APR_ARRAY_PUSH(younger_rangelist, svn_merge_range_t *) =
676                     younger_range;
677                 }
678
679               /* So far we've only been manipulating rangelists, now we
680                  actually create *YOUNGER_MERGEINFO and then remove the older
681                  ranges from *MERGEINFO */
682               if (!(*younger_mergeinfo))
683                 *younger_mergeinfo = apr_hash_make(pool);
684               svn_hash_sets(*younger_mergeinfo, merge_source_path,
685                             younger_rangelist);
686               SVN_ERR(svn_mergeinfo_remove2(mergeinfo, *younger_mergeinfo,
687                                             *mergeinfo, TRUE, pool, iterpool));
688               break; /* ...out of for (i = 0; i < rangelist->nelts; i++) */
689             }
690         }
691     }
692
693   svn_pool_destroy(iterpool);
694
695   return SVN_NO_ERROR;
696 }
697
698
699 /* Make a copy of PROPCHANGES (array of svn_prop_t) into *TRIMMED_PROPCHANGES,
700    omitting any svn:mergeinfo changes.  */
701 static svn_error_t *
702 omit_mergeinfo_changes(apr_array_header_t **trimmed_propchanges,
703                        const apr_array_header_t *propchanges,
704                        apr_pool_t *result_pool)
705 {
706   int i;
707
708   *trimmed_propchanges = apr_array_make(result_pool,
709                                         propchanges->nelts,
710                                         sizeof(svn_prop_t));
711
712   for (i = 0; i < propchanges->nelts; ++i)
713     {
714       const svn_prop_t *change = &APR_ARRAY_IDX(propchanges, i, svn_prop_t);
715
716       /* If this property is not svn:mergeinfo, then copy it.  */
717       if (strcmp(change->name, SVN_PROP_MERGEINFO) != 0)
718         APR_ARRAY_PUSH(*trimmed_propchanges, svn_prop_t) = *change;
719     }
720
721   return SVN_NO_ERROR;
722 }
723
724
725 /* Helper for merge_props_changed().
726
727    *PROPS is an array of svn_prop_t structures representing regular properties
728    to be added to the working copy TARGET_ABSPATH.
729
730    The merge source and target are assumed to be in the same repository.
731
732    Filter out mergeinfo property additions to TARGET_ABSPATH when
733    those additions refer to the same line of history as TARGET_ABSPATH as
734    described below.
735
736    Examine the added mergeinfo, looking at each range (or single rev)
737    of each source path.  If a source_path/range refers to the same line of
738    history as TARGET_ABSPATH (pegged at its base revision), then filter out
739    that range.  If the entire rangelist for a given path is filtered then
740    filter out the path as well.
741
742    RA_SESSION is an open RA session to the repository
743    in which both the source and target live, else RA_SESSION is not used. It
744    may be temporarily reparented as needed by this function.
745
746    Use CTX for any further client operations.
747
748    If any filtering occurs, set outgoing *PROPS to a shallow copy (allocated
749    in POOL) of incoming *PROPS minus the filtered mergeinfo. */
750 static svn_error_t *
751 filter_self_referential_mergeinfo(apr_array_header_t **props,
752                                   const char *target_abspath,
753                                   svn_ra_session_t *ra_session,
754                                   svn_client_ctx_t *ctx,
755                                   apr_pool_t *pool)
756 {
757   apr_array_header_t *adjusted_props;
758   int i;
759   apr_pool_t *iterpool;
760   svn_boolean_t is_copy;
761   const char *repos_relpath;
762   svn_client__pathrev_t target_base;
763
764   /* If PATH itself has been added there is no need to filter. */
765   SVN_ERR(svn_wc__node_get_origin(&is_copy,  &target_base.rev, &repos_relpath,
766                                   &target_base.repos_root_url,
767                                   &target_base.repos_uuid, NULL,
768                                   ctx->wc_ctx, target_abspath, FALSE,
769                                   pool, pool));
770
771   if (is_copy || !repos_relpath)
772     return SVN_NO_ERROR; /* A copy or a local addition */
773
774   target_base.url = svn_path_url_add_component2(target_base.repos_root_url,
775                                                 repos_relpath, pool);
776
777   adjusted_props = apr_array_make(pool, (*props)->nelts, sizeof(svn_prop_t));
778   iterpool = svn_pool_create(pool);
779   for (i = 0; i < (*props)->nelts; ++i)
780     {
781       svn_prop_t *prop = &APR_ARRAY_IDX((*props), i, svn_prop_t);
782
783       svn_mergeinfo_t mergeinfo, younger_mergeinfo;
784       svn_mergeinfo_t filtered_mergeinfo = NULL;
785       svn_mergeinfo_t filtered_younger_mergeinfo = NULL;
786       svn_error_t *err;
787
788       /* If this property isn't mergeinfo or is NULL valued (i.e. prop removal)
789          or empty mergeinfo it does not require any special handling.  There
790          is nothing to filter out of empty mergeinfo and the concept of
791          filtering doesn't apply if we are trying to remove mergeinfo
792          entirely.  */
793       if ((strcmp(prop->name, SVN_PROP_MERGEINFO) != 0)
794           || (! prop->value)       /* Removal of mergeinfo */
795           || (! prop->value->len)) /* Empty mergeinfo */
796         {
797           APR_ARRAY_PUSH(adjusted_props, svn_prop_t) = *prop;
798           continue;
799         }
800
801       svn_pool_clear(iterpool);
802
803       /* Non-empty mergeinfo; filter self-referential mergeinfo out. */
804
805       /* Parse the incoming mergeinfo to allow easier manipulation. */
806       err = svn_mergeinfo_parse(&mergeinfo, prop->value->data, iterpool);
807
808       if (err)
809         {
810           /* Issue #3896: If we can't parse it, we certainly can't
811              filter it. */
812           if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
813             {
814               svn_error_clear(err);
815               APR_ARRAY_PUSH(adjusted_props, svn_prop_t) = *prop;
816               continue;
817             }
818           else
819             {
820               return svn_error_trace(err);
821             }
822         }
823
824       /* The working copy target PATH is at BASE_REVISION.  Divide the
825          incoming mergeinfo into two groups.  One where all revision ranges
826          are as old or older than BASE_REVISION and one where all revision
827          ranges are younger.
828
829          Note: You may be wondering why we do this.
830
831          For the incoming mergeinfo "older" than target's base revision we
832          can filter out self-referential mergeinfo efficiently using
833          svn_client__get_history_as_mergeinfo().  We simply look at PATH's
834          natural history as mergeinfo and remove that from any incoming
835          mergeinfo.
836
837          For mergeinfo "younger" than the base revision we can't use
838          svn_ra_get_location_segments() to look into PATH's future
839          history.  Instead we must use svn_client__repos_locations() and
840          look at each incoming source/range individually and see if PATH
841          at its base revision and PATH at the start of the incoming range
842          exist on the same line of history.  If they do then we can filter
843          out the incoming range.  But since we have to do this for each
844          range there is a substantial performance penalty to pay if the
845          incoming ranges are not contiguous, i.e. we call
846          svn_client__repos_locations for each discrete range and incur
847          the cost of a roundtrip communication with the repository. */
848       SVN_ERR(split_mergeinfo_on_revision(&younger_mergeinfo,
849                                           &mergeinfo,
850                                           target_base.rev,
851                                           iterpool));
852
853       /* Filter self-referential mergeinfo from younger_mergeinfo. */
854       if (younger_mergeinfo)
855         {
856           apr_hash_index_t *hi;
857           const char *merge_source_root_url;
858
859           SVN_ERR(svn_ra_get_repos_root2(ra_session,
860                                          &merge_source_root_url, iterpool));
861
862           for (hi = apr_hash_first(iterpool, younger_mergeinfo);
863                hi; hi = apr_hash_next(hi))
864             {
865               int j;
866               const char *source_path = svn__apr_hash_index_key(hi);
867               svn_rangelist_t *rangelist = svn__apr_hash_index_val(hi);
868               const char *merge_source_url;
869               svn_rangelist_t *adjusted_rangelist =
870                 apr_array_make(iterpool, 0, sizeof(svn_merge_range_t *));
871
872               merge_source_url =
873                     svn_path_url_add_component2(merge_source_root_url,
874                                                 source_path + 1, iterpool);
875
876               for (j = 0; j < rangelist->nelts; j++)
877                 {
878                   svn_error_t *err2;
879                   svn_client__pathrev_t *start_loc;
880                   svn_merge_range_t *range =
881                     APR_ARRAY_IDX(rangelist, j, svn_merge_range_t *);
882
883                   /* Because the merge source normalization code
884                      ensures mergeinfo refers to real locations on
885                      the same line of history, there's no need to
886                      look at the whole range, just the start. */
887
888                   /* Check if PATH@BASE_REVISION exists at
889                      RANGE->START on the same line of history.
890                      (start+1 because RANGE->start is not inclusive.) */
891                   err2 = svn_client__repos_location(&start_loc, ra_session,
892                                                     &target_base,
893                                                     range->start + 1,
894                                                     ctx, iterpool, iterpool);
895                   if (err2)
896                     {
897                       if (err2->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES
898                           || err2->apr_err == SVN_ERR_FS_NOT_FOUND
899                           || err2->apr_err == SVN_ERR_FS_NO_SUCH_REVISION)
900                         {
901                           /* PATH@BASE_REVISION didn't exist at
902                              RANGE->START + 1 or is unrelated to the
903                              resource PATH@RANGE->START.  Some of the
904                              requested revisions may not even exist in
905                              the repository; a real possibility since
906                              mergeinfo is hand editable.  In all of these
907                              cases clear and ignore the error and don't
908                              do any filtering.
909
910                              Note: In this last case it is possible that
911                              we will allow self-referential mergeinfo to
912                              be applied, but fixing it here is potentially
913                              very costly in terms of finding what part of
914                              a range is actually valid.  Simply allowing
915                              the merge to proceed without filtering the
916                              offending range seems the least worst
917                              option. */
918                           svn_error_clear(err2);
919                           err2 = NULL;
920                           APR_ARRAY_PUSH(adjusted_rangelist,
921                                          svn_merge_range_t *) = range;
922                         }
923                       else
924                         {
925                           return svn_error_trace(err2);
926                         }
927                      }
928                   else
929                     {
930                       /* PATH@BASE_REVISION exists on the same
931                          line of history at RANGE->START and RANGE->END.
932                          Now check that PATH@BASE_REVISION's path
933                          names at RANGE->START and RANGE->END are the same.
934                          If the names are not the same then the mergeinfo
935                          describing PATH@RANGE->START through
936                          PATH@RANGE->END actually belong to some other
937                          line of history and we want to record this
938                          mergeinfo, not filter it. */
939                       if (strcmp(start_loc->url, merge_source_url) != 0)
940                         {
941                           APR_ARRAY_PUSH(adjusted_rangelist,
942                                          svn_merge_range_t *) = range;
943                         }
944                     }
945                     /* else no need to add, this mergeinfo is
946                        all on the same line of history. */
947                 } /* for (j = 0; j < rangelist->nelts; j++) */
948
949               /* Add any rangelists for source_path that are not
950                  self-referential. */
951               if (adjusted_rangelist->nelts)
952                 {
953                   if (!filtered_younger_mergeinfo)
954                     filtered_younger_mergeinfo = apr_hash_make(iterpool);
955                   svn_hash_sets(filtered_younger_mergeinfo, source_path,
956                                 adjusted_rangelist);
957                 }
958
959             } /* Iteration over each merge source in younger_mergeinfo. */
960         } /* if (younger_mergeinfo) */
961
962       /* Filter self-referential mergeinfo from "older" mergeinfo. */
963       if (mergeinfo)
964         {
965           svn_mergeinfo_t implicit_mergeinfo;
966
967           SVN_ERR(svn_client__get_history_as_mergeinfo(
968             &implicit_mergeinfo, NULL,
969             &target_base, target_base.rev, SVN_INVALID_REVNUM,
970             ra_session, ctx, iterpool));
971
972           /* Remove PATH's implicit mergeinfo from the incoming mergeinfo. */
973           SVN_ERR(svn_mergeinfo_remove2(&filtered_mergeinfo,
974                                         implicit_mergeinfo,
975                                         mergeinfo, TRUE, iterpool, iterpool));
976         }
977
978       /* Combine whatever older and younger filtered mergeinfo exists
979          into filtered_mergeinfo. */
980       if (filtered_mergeinfo && filtered_younger_mergeinfo)
981         SVN_ERR(svn_mergeinfo_merge2(filtered_mergeinfo,
982                                      filtered_younger_mergeinfo, iterpool,
983                                      iterpool));
984       else if (filtered_younger_mergeinfo)
985         filtered_mergeinfo = filtered_younger_mergeinfo;
986
987       /* If there is any incoming mergeinfo remaining after filtering
988          then put it in adjusted_props. */
989       if (filtered_mergeinfo && apr_hash_count(filtered_mergeinfo))
990         {
991           /* Convert filtered_mergeinfo to a svn_prop_t and put it
992              back in the array. */
993           svn_string_t *filtered_mergeinfo_str;
994           svn_prop_t *adjusted_prop = apr_pcalloc(pool,
995                                                   sizeof(*adjusted_prop));
996           SVN_ERR(svn_mergeinfo_to_string(&filtered_mergeinfo_str,
997                                           filtered_mergeinfo,
998                                           pool));
999           adjusted_prop->name = SVN_PROP_MERGEINFO;
1000           adjusted_prop->value = filtered_mergeinfo_str;
1001           APR_ARRAY_PUSH(adjusted_props, svn_prop_t) = *adjusted_prop;
1002         }
1003     }
1004   svn_pool_destroy(iterpool);
1005
1006   *props = adjusted_props;
1007   return SVN_NO_ERROR;
1008 }
1009
1010 /* Prepare a set of property changes PROPCHANGES to be used for a merge
1011    operation on LOCAL_ABSPATH.
1012
1013    Remove all non-regular prop-changes (entry-props and WC-props).
1014    Remove all non-mergeinfo prop-changes if it's a record-only merge.
1015    Remove self-referential mergeinfo (### in some cases...)
1016    Remove foreign-repository mergeinfo (### in some cases...)
1017
1018    Store the resulting property changes in *PROP_UPDATES.
1019    Store information on where mergeinfo is updated in MERGE_B.
1020
1021    Used for both file and directory property merges. */
1022 static svn_error_t *
1023 prepare_merge_props_changed(const apr_array_header_t **prop_updates,
1024                             const char *local_abspath,
1025                             const apr_array_header_t *propchanges,
1026                             merge_cmd_baton_t *merge_b,
1027                             apr_pool_t *result_pool,
1028                             apr_pool_t *scratch_pool)
1029 {
1030   apr_array_header_t *props;
1031
1032   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
1033
1034   /* We only want to merge "regular" version properties:  by
1035      definition, 'svn merge' shouldn't touch any data within .svn/  */
1036   SVN_ERR(svn_categorize_props(propchanges, NULL, NULL, &props,
1037                                result_pool));
1038
1039   /* If we are only applying mergeinfo changes then we need to do
1040      additional filtering of PROPS so it contains only mergeinfo changes. */
1041   if (merge_b->record_only && props->nelts)
1042     {
1043       apr_array_header_t *mergeinfo_props =
1044         apr_array_make(result_pool, 1, sizeof(svn_prop_t));
1045       int i;
1046
1047       for (i = 0; i < props->nelts; i++)
1048         {
1049           svn_prop_t *prop = &APR_ARRAY_IDX(props, i, svn_prop_t);
1050
1051           if (strcmp(prop->name, SVN_PROP_MERGEINFO) == 0)
1052             {
1053               APR_ARRAY_PUSH(mergeinfo_props, svn_prop_t) = *prop;
1054               break;
1055             }
1056         }
1057       props = mergeinfo_props;
1058     }
1059
1060   if (props->nelts)
1061     {
1062       /* Issue #3383: We don't want mergeinfo from a foreign repos.
1063
1064          If this is a merge from a foreign repository we must strip all
1065          incoming mergeinfo (including mergeinfo deletions). */
1066       if (! merge_b->same_repos)
1067         SVN_ERR(omit_mergeinfo_changes(&props, props, result_pool));
1068
1069       /* If this is a forward merge then don't add new mergeinfo to
1070          PATH that is already part of PATH's own history, see
1071          http://svn.haxx.se/dev/archive-2008-09/0006.shtml.  If the
1072          merge sources are not ancestral then there is no concept of a
1073          'forward' or 'reverse' merge and we filter unconditionally. */
1074       if (merge_b->merge_source.loc1->rev < merge_b->merge_source.loc2->rev
1075           || !merge_b->merge_source.ancestral)
1076         {
1077           if (HONOR_MERGEINFO(merge_b) || merge_b->reintegrate_merge)
1078             SVN_ERR(filter_self_referential_mergeinfo(&props,
1079                                                       local_abspath,
1080                                                       merge_b->ra_session2,
1081                                                       merge_b->ctx,
1082                                                       result_pool));
1083         }
1084     }
1085   *prop_updates = props;
1086
1087   /* Make a record in BATON if we find a PATH where mergeinfo is added
1088      where none existed previously or PATH is having its existing
1089      mergeinfo deleted. */
1090   if (props->nelts)
1091     {
1092       int i;
1093
1094       for (i = 0; i < props->nelts; ++i)
1095         {
1096           svn_prop_t *prop = &APR_ARRAY_IDX(props, i, svn_prop_t);
1097
1098           if (strcmp(prop->name, SVN_PROP_MERGEINFO) == 0)
1099             {
1100               /* Does LOCAL_ABSPATH have any pristine mergeinfo? */
1101               svn_boolean_t has_pristine_mergeinfo = FALSE;
1102               apr_hash_t *pristine_props;
1103
1104               SVN_ERR(svn_wc_get_pristine_props(&pristine_props,
1105                                                 merge_b->ctx->wc_ctx,
1106                                                 local_abspath,
1107                                                 scratch_pool,
1108                                                 scratch_pool));
1109
1110               if (pristine_props
1111                   && svn_hash_gets(pristine_props, SVN_PROP_MERGEINFO))
1112                 has_pristine_mergeinfo = TRUE;
1113
1114               if (!has_pristine_mergeinfo && prop->value)
1115                 {
1116                   alloc_and_store_path(&merge_b->paths_with_new_mergeinfo,
1117                                        local_abspath, merge_b->pool);
1118                 }
1119               else if (has_pristine_mergeinfo && !prop->value)
1120                 {
1121                   alloc_and_store_path(&merge_b->paths_with_deleted_mergeinfo,
1122                                        local_abspath, merge_b->pool);
1123                 }
1124             }
1125         }
1126     }
1127
1128   return SVN_NO_ERROR;
1129 }
1130
1131 #define CONFLICT_REASON_NONE       ((svn_wc_conflict_reason_t)-1)
1132 #define CONFLICT_REASON_SKIP       ((svn_wc_conflict_reason_t)-2)
1133 #define CONFLICT_REASON_SKIP_WC    ((svn_wc_conflict_reason_t)-3)
1134
1135 /* Baton used for testing trees for being editted while performing tree
1136    conflict detection for incoming deletes */
1137 struct dir_delete_baton_t
1138 {
1139   /* Reference to dir baton of directory that is the root of the deletion */
1140   struct merge_dir_baton_t *del_root;
1141
1142   /* Boolean indicating that some edit is found. Allows avoiding more work */
1143   svn_boolean_t found_edit;
1144
1145   /* A list of paths that are compared. Kept up to date until FOUND_EDIT is
1146      set to TRUE */
1147   apr_hash_t *compared_abspaths;
1148 };
1149
1150 /* Baton for the merge_dir_*() functions. Initialized in merge_dir_opened() */
1151 struct merge_dir_baton_t
1152 {
1153   /* Reference to the parent baton, unless the parent is the anchor, in which
1154      case PARENT_BATON is NULL */
1155   struct merge_dir_baton_t *parent_baton;
1156
1157   /* The pool containing this baton. Use for RESULT_POOL for storing in this
1158      baton */
1159   apr_pool_t *pool;
1160
1161   /* This directory doesn't have a representation in the working copy, so any
1162      operation on it will be skipped and possibly cause a tree conflict on the
1163      shadow root */
1164   svn_boolean_t shadowed;
1165
1166   /* This node or one of its descendants received operational changes from the
1167      merge. If this node is the shadow root its tree conflict status has been
1168      applied */
1169   svn_boolean_t edited;
1170
1171   /* If a tree conflict will be installed once edited, it's reason. If a skip
1172      should be produced its reason. Otherwise CONFLICT_REASON_NONE for no tree
1173      conflict.
1174
1175      Special values:
1176        CONFLICT_REASON_SKIP:
1177             The node will be skipped with content and property state as stored in
1178             SKIP_REASON.
1179
1180        CONFLICT_REASON_SKIP_WC:
1181             The node will be skipped as an obstructing working copy.
1182    */
1183   svn_wc_conflict_reason_t tree_conflict_reason;
1184   svn_wc_conflict_action_t tree_conflict_action;
1185
1186   /* When TREE_CONFLICT_REASON is CONFLICT_REASON_SKIP, the skip state to
1187      add to the notification */
1188   svn_wc_notify_state_t skip_reason;
1189
1190   /* TRUE if the node was added by this merge. Otherwise FALSE */
1191   svn_boolean_t added;
1192   svn_boolean_t add_is_replace; /* Add is second part of replace */
1193
1194   /* TRUE if we are taking over an existing directory as addition, otherwise
1195      FALSE. */
1196   svn_boolean_t add_existing;
1197
1198   /* NULL, or an hashtable mapping const char * local_abspaths to
1199      const char *kind mapping, containing deleted nodes that still need a delete
1200      notification (which may be a replaced notification if the node is not just
1201      deleted) */
1202   apr_hash_t *pending_deletes;
1203
1204   /* NULL, or an hashtable mapping const char * LOCAL_ABSPATHs to
1205      a const svn_wc_conflict_description2_t * instance, describing the just
1206      installed conflict */
1207   apr_hash_t *new_tree_conflicts;
1208
1209   /* If not NULL, a reference to the information of the delete test that is
1210      currently in progress. Allocated in the root-directory baton, referenced
1211      from all descendants */
1212   struct dir_delete_baton_t *delete_state;
1213 };
1214
1215 /* Baton for the merge_dir_*() functions. Initialized in merge_file_opened() */
1216 struct merge_file_baton_t
1217 {
1218   /* Reference to the parent baton, unless the parent is the anchor, in which
1219      case PARENT_BATON is NULL */
1220   struct merge_dir_baton_t *parent_baton;
1221
1222   /* This file doesn't have a representation in the working copy, so any
1223      operation on it will be skipped and possibly cause a tree conflict
1224      on the shadow root */
1225   svn_boolean_t shadowed;
1226
1227   /* This node received operational changes from the merge. If this node
1228      is the shadow root its tree conflict status has been applied */
1229   svn_boolean_t edited;
1230
1231   /* If a tree conflict will be installed once edited, it's reason. If a skip
1232      should be produced its reason. Some special values are defined. See the
1233      merge_tree_baton_t for an explanation. */
1234   svn_wc_conflict_reason_t tree_conflict_reason;
1235   svn_wc_conflict_action_t tree_conflict_action;
1236
1237   /* When TREE_CONFLICT_REASON is CONFLICT_REASON_SKIP, the skip state to
1238      add to the notification */
1239   svn_wc_notify_state_t skip_reason;
1240
1241   /* TRUE if the node was added by this merge. Otherwise FALSE */
1242   svn_boolean_t added;
1243   svn_boolean_t add_is_replace; /* Add is second part of replace */
1244 };
1245
1246 /* Forward declaration */
1247 static svn_error_t *
1248 notify_merge_begin(merge_cmd_baton_t *merge_b,
1249                    const char *local_abspath,
1250                    svn_boolean_t delete_action,
1251                    apr_pool_t *scratch_pool);
1252
1253 /* Record the skip for future processing and (later) produce the
1254    skip notification */
1255 static svn_error_t *
1256 record_skip(merge_cmd_baton_t *merge_b,
1257             const char *local_abspath,
1258             svn_node_kind_t kind,
1259             svn_wc_notify_action_t action,
1260             svn_wc_notify_state_t state,
1261             struct merge_dir_baton_t *pdb,
1262             apr_pool_t *scratch_pool)
1263 {
1264   if (merge_b->record_only)
1265     return SVN_NO_ERROR; /* ### Why? - Legacy compatibility */
1266
1267   if ((merge_b->merge_source.ancestral || merge_b->reintegrate_merge)
1268       && !(pdb && pdb->shadowed))
1269     {
1270       store_path(merge_b->skipped_abspaths, local_abspath);
1271     }
1272
1273   if (merge_b->ctx->notify_func2)
1274     {
1275       svn_wc_notify_t *notify;
1276
1277       SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE, scratch_pool));
1278
1279       notify = svn_wc_create_notify(local_abspath, action, scratch_pool);
1280       notify->kind = kind;
1281       notify->content_state = notify->prop_state = state;
1282
1283       (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2, notify,
1284                                     scratch_pool);
1285     }
1286   return SVN_NO_ERROR;
1287 }
1288
1289 /* Record a tree conflict in the WC, unless this is a dry run or a record-
1290  * only merge, or if a tree conflict is already flagged for the VICTIM_PATH.
1291  * (The latter can happen if a merge-tracking-aware merge is doing multiple
1292  * editor drives because of a gap in the range of eligible revisions.)
1293  *
1294  * The tree conflict, with its victim specified by VICTIM_PATH, is
1295  * assumed to have happened during a merge using merge baton MERGE_B.
1296  *
1297  * NODE_KIND must be the node kind of "old" and "theirs" and "mine";
1298  * this function cannot cope with node kind clashes.
1299  * ACTION and REASON correspond to the fields
1300  * of the same names in svn_wc_tree_conflict_description_t.
1301  */
1302 static svn_error_t *
1303 record_tree_conflict(merge_cmd_baton_t *merge_b,
1304                      const char *local_abspath,
1305                      struct merge_dir_baton_t *parent_baton,
1306                      svn_node_kind_t node_kind,
1307                      svn_wc_conflict_action_t action,
1308                      svn_wc_conflict_reason_t reason,
1309                      const svn_wc_conflict_description2_t *existing_conflict,
1310                      svn_boolean_t notify_tc,
1311                      apr_pool_t *scratch_pool)
1312 {
1313   svn_wc_context_t *wc_ctx = merge_b->ctx->wc_ctx;
1314
1315   if (merge_b->record_only)
1316     return SVN_NO_ERROR;
1317
1318   if (merge_b->merge_source.ancestral
1319       || merge_b->reintegrate_merge)
1320     {
1321       store_path(merge_b->tree_conflicted_abspaths, local_abspath);
1322     }
1323
1324   alloc_and_store_path(&merge_b->conflicted_paths, local_abspath,
1325                        merge_b->pool);
1326
1327   if (!merge_b->dry_run)
1328     {
1329        svn_wc_conflict_description2_t *conflict;
1330        const svn_wc_conflict_version_t *left;
1331        const svn_wc_conflict_version_t *right;
1332        apr_pool_t *result_pool = parent_baton ? parent_baton->pool
1333                                               : scratch_pool;
1334
1335       if (reason == svn_wc_conflict_reason_deleted)
1336         {
1337           const char *moved_to_abspath;
1338
1339           SVN_ERR(svn_wc__node_was_moved_away(&moved_to_abspath, NULL,
1340                                               wc_ctx, local_abspath,
1341                                               scratch_pool, scratch_pool));
1342
1343           if (moved_to_abspath)
1344             {
1345               /* Local abspath itself has been moved away. If only a
1346                  descendant is moved away, we call the node itself deleted */
1347               reason = svn_wc_conflict_reason_moved_away;
1348             }
1349         }
1350       else if (reason == svn_wc_conflict_reason_added)
1351         {
1352           const char *moved_from_abspath;
1353           SVN_ERR(svn_wc__node_was_moved_here(&moved_from_abspath, NULL,
1354                                               wc_ctx, local_abspath,
1355                                               scratch_pool, scratch_pool));
1356           if (moved_from_abspath)
1357             reason = svn_wc_conflict_reason_moved_here;
1358         }
1359
1360       SVN_ERR(make_conflict_versions(&left, &right, local_abspath, node_kind,
1361                                      &merge_b->merge_source, merge_b->target,
1362                                      result_pool, scratch_pool));
1363
1364       /* Fix up delete of file, add of dir replacement (or other way around) */
1365       if (existing_conflict != NULL && existing_conflict->src_left_version)
1366           left = existing_conflict->src_left_version;
1367
1368       conflict = svn_wc_conflict_description_create_tree2(
1369                         local_abspath, node_kind, svn_wc_operation_merge,
1370                         left, right, result_pool);
1371
1372       conflict->action = action;
1373       conflict->reason = reason;
1374
1375       /* May return SVN_ERR_WC_PATH_UNEXPECTED_STATUS */
1376       if (existing_conflict)
1377         SVN_ERR(svn_wc__del_tree_conflict(wc_ctx, local_abspath,
1378                                           scratch_pool));
1379
1380       SVN_ERR(svn_wc__add_tree_conflict(merge_b->ctx->wc_ctx, conflict,
1381                                         scratch_pool));
1382
1383       if (parent_baton)
1384         {
1385           if (! parent_baton->new_tree_conflicts)
1386             parent_baton->new_tree_conflicts = apr_hash_make(result_pool);
1387
1388           svn_hash_sets(parent_baton->new_tree_conflicts,
1389                         apr_pstrdup(result_pool, local_abspath),
1390                         conflict);
1391         }
1392
1393       /* ### TODO: Store in parent baton */
1394     }
1395
1396   /* On a replacement we currently get two tree conflicts */
1397   if (merge_b->ctx->notify_func2 && notify_tc)
1398     {
1399       svn_wc_notify_t *notify;
1400
1401       SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE, scratch_pool));
1402
1403       notify = svn_wc_create_notify(local_abspath, svn_wc_notify_tree_conflict,
1404                                     scratch_pool);
1405       notify->kind = node_kind;
1406
1407       (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2, notify,
1408                                     scratch_pool);
1409     }
1410
1411   return SVN_NO_ERROR;
1412 }
1413
1414 /* Record the add for future processing and produce the
1415    update_add notification
1416  */
1417 static svn_error_t *
1418 record_update_add(merge_cmd_baton_t *merge_b,
1419                   const char *local_abspath,
1420                   svn_node_kind_t kind,
1421                   svn_boolean_t notify_replaced,
1422                   apr_pool_t *scratch_pool)
1423 {
1424   if (merge_b->merge_source.ancestral || merge_b->reintegrate_merge)
1425     {
1426       store_path(merge_b->merged_abspaths, local_abspath);
1427     }
1428
1429   if (merge_b->ctx->notify_func2)
1430     {
1431       svn_wc_notify_t *notify;
1432       svn_wc_notify_action_t action = svn_wc_notify_update_add;
1433
1434       SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE, scratch_pool));
1435
1436       if (notify_replaced)
1437         action = svn_wc_notify_update_replace;
1438
1439       notify = svn_wc_create_notify(local_abspath, action, scratch_pool);
1440       notify->kind = kind;
1441
1442       (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2, notify,
1443                                     scratch_pool);
1444     }
1445
1446   return SVN_NO_ERROR;
1447 }
1448
1449 /* Record the update for future processing and produce the
1450    update_update notification */
1451 static svn_error_t *
1452 record_update_update(merge_cmd_baton_t *merge_b,
1453                      const char *local_abspath,
1454                      svn_node_kind_t kind,
1455                      svn_wc_notify_state_t content_state,
1456                      svn_wc_notify_state_t prop_state,
1457                      apr_pool_t *scratch_pool)
1458 {
1459   if (merge_b->merge_source.ancestral || merge_b->reintegrate_merge)
1460     {
1461       store_path(merge_b->merged_abspaths, local_abspath);
1462     }
1463
1464   if (merge_b->ctx->notify_func2)
1465     {
1466       svn_wc_notify_t *notify;
1467
1468       SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE, scratch_pool));
1469
1470       notify = svn_wc_create_notify(local_abspath, svn_wc_notify_update_update,
1471                                     scratch_pool);
1472       notify->kind = kind;
1473       notify->content_state = content_state;
1474       notify->prop_state = prop_state;
1475
1476       (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2, notify,
1477                                     scratch_pool);
1478     }
1479
1480   return SVN_NO_ERROR;
1481 }
1482
1483 /* Record the delete for future processing and for (later) producing the
1484    update_delete notification */
1485 static svn_error_t *
1486 record_update_delete(merge_cmd_baton_t *merge_b,
1487                      struct merge_dir_baton_t *parent_db,
1488                      const char *local_abspath,
1489                      svn_node_kind_t kind,
1490                      apr_pool_t *scratch_pool)
1491 {
1492   /* Update the lists of merged, skipped, tree-conflicted and added paths. */
1493   if (merge_b->merge_source.ancestral
1494       || merge_b->reintegrate_merge)
1495     {
1496       /* Issue #4166: If a previous merge added NOTIFY_ABSPATH, but we
1497          are now deleting it, then remove it from the list of added
1498          paths. */
1499       svn_hash_sets(merge_b->added_abspaths, local_abspath, NULL);
1500       store_path(merge_b->merged_abspaths, local_abspath);
1501     }
1502
1503   SVN_ERR(notify_merge_begin(merge_b, local_abspath, TRUE, scratch_pool));
1504
1505   if (parent_db)
1506     {
1507       const char *dup_abspath = apr_pstrdup(parent_db->pool, local_abspath);
1508
1509       if (!parent_db->pending_deletes)
1510         parent_db->pending_deletes = apr_hash_make(parent_db->pool);
1511
1512       svn_hash_sets(parent_db->pending_deletes, dup_abspath,
1513                     svn_node_kind_to_word(kind));
1514     }
1515
1516   return SVN_NO_ERROR;
1517 }
1518
1519 /* Notify the pending 'D'eletes, that were waiting to see if a matching 'A'dd
1520    might make them a 'R'eplace. */
1521 static svn_error_t *
1522 handle_pending_notifications(merge_cmd_baton_t *merge_b,
1523                              struct merge_dir_baton_t *db,
1524                              apr_pool_t *scratch_pool)
1525 {
1526   if (merge_b->ctx->notify_func2 && db->pending_deletes)
1527     {
1528       apr_hash_index_t *hi;
1529
1530       for (hi = apr_hash_first(scratch_pool, db->pending_deletes);
1531            hi;
1532            hi = apr_hash_next(hi))
1533         {
1534           const char *del_abspath = svn__apr_hash_index_key(hi);
1535           svn_wc_notify_t *notify;
1536
1537           notify = svn_wc_create_notify(del_abspath,
1538                                         svn_wc_notify_update_delete,
1539                                         scratch_pool);
1540           notify->kind = svn_node_kind_from_word(
1541                                     svn__apr_hash_index_val(hi));
1542
1543           (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2,
1544                                         notify, scratch_pool);
1545         }
1546
1547       db->pending_deletes = NULL;
1548     }
1549   return SVN_NO_ERROR;
1550 }
1551
1552 /* Helper function for the merge_dir_*() and merge_file_*() functions.
1553
1554    Installs and notifies pre-recorded tree conflicts and skips for
1555    ancestors of operational merges
1556  */
1557 static svn_error_t *
1558 mark_dir_edited(merge_cmd_baton_t *merge_b,
1559                 struct merge_dir_baton_t *db,
1560                 const char *local_abspath,
1561                 apr_pool_t *scratch_pool)
1562 {
1563   /* ### Too much common code with mark_file_edited */
1564   if (db->edited)
1565     return SVN_NO_ERROR;
1566
1567   if (db->parent_baton && !db->parent_baton->edited)
1568     {
1569       const char *dir_abspath = svn_dirent_dirname(local_abspath,
1570                                                    scratch_pool);
1571
1572       SVN_ERR(mark_dir_edited(merge_b, db->parent_baton, dir_abspath,
1573                               scratch_pool));
1574     }
1575
1576   db->edited = TRUE;
1577
1578   if (! db->shadowed)
1579     return SVN_NO_ERROR; /* Easy out */
1580
1581   if (db->parent_baton
1582       && db->parent_baton->delete_state
1583       && db->tree_conflict_reason != CONFLICT_REASON_NONE)
1584     {
1585       db->parent_baton->delete_state->found_edit = TRUE;
1586     }
1587   else if (db->tree_conflict_reason == CONFLICT_REASON_SKIP
1588            || db->tree_conflict_reason == CONFLICT_REASON_SKIP_WC)
1589     {
1590       /* open_directory() decided not to flag a tree conflict, but
1591          for clarity we produce a skip for this node that
1592          most likely isn't touched by the merge itself */
1593
1594       if (merge_b->ctx->notify_func2)
1595         {
1596           svn_wc_notify_t *notify;
1597
1598           SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE,
1599                                      scratch_pool));
1600
1601           notify = svn_wc_create_notify(
1602                             local_abspath,
1603                             (db->tree_conflict_reason == CONFLICT_REASON_SKIP)
1604                                 ? svn_wc_notify_skip
1605                                 : svn_wc_notify_update_skip_obstruction,
1606                             scratch_pool);
1607           notify->kind = svn_node_dir;
1608           notify->content_state = notify->prop_state = db->skip_reason;
1609
1610           (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2,
1611                                         notify,
1612                                         scratch_pool);
1613         }
1614
1615       if (merge_b->merge_source.ancestral
1616           || merge_b->reintegrate_merge)
1617         {
1618           store_path(merge_b->skipped_abspaths, local_abspath);
1619         }
1620     }
1621   else if (db->tree_conflict_reason != CONFLICT_REASON_NONE)
1622     {
1623       /* open_directory() decided that a tree conflict should be raised */
1624
1625       SVN_ERR(record_tree_conflict(merge_b, local_abspath, db->parent_baton,
1626                                    svn_node_dir, db->tree_conflict_action,
1627                                    db->tree_conflict_reason,
1628                                    NULL, TRUE,
1629                                    scratch_pool));
1630     }
1631
1632   return SVN_NO_ERROR;
1633 }
1634
1635 /* Helper function for the merge_file_*() functions.
1636
1637    Installs and notifies pre-recorded tree conflicts and skips for
1638    ancestors of operational merges
1639  */
1640 static svn_error_t *
1641 mark_file_edited(merge_cmd_baton_t *merge_b,
1642                  struct merge_file_baton_t *fb,
1643                  const char *local_abspath,
1644                  apr_pool_t *scratch_pool)
1645 {
1646   /* ### Too much common code with mark_dir_edited */
1647   if (fb->edited)
1648     return SVN_NO_ERROR;
1649
1650   if (fb->parent_baton && !fb->parent_baton->edited)
1651     {
1652       const char *dir_abspath = svn_dirent_dirname(local_abspath,
1653                                                    scratch_pool);
1654
1655       SVN_ERR(mark_dir_edited(merge_b, fb->parent_baton, dir_abspath,
1656                               scratch_pool));
1657     }
1658
1659   fb->edited = TRUE;
1660
1661   if (! fb->shadowed)
1662     return SVN_NO_ERROR; /* Easy out */
1663
1664   if (fb->parent_baton
1665       && fb->parent_baton->delete_state
1666       && fb->tree_conflict_reason != CONFLICT_REASON_NONE)
1667     {
1668       fb->parent_baton->delete_state->found_edit = TRUE;
1669     }
1670   else if (fb->tree_conflict_reason == CONFLICT_REASON_SKIP
1671            || fb->tree_conflict_reason == CONFLICT_REASON_SKIP_WC)
1672     {
1673       /* open_directory() decided not to flag a tree conflict, but
1674          for clarity we produce a skip for this node that
1675          most likely isn't touched by the merge itself */
1676
1677       if (merge_b->ctx->notify_func2)
1678         {
1679           svn_wc_notify_t *notify;
1680
1681           SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE,
1682                                      scratch_pool));
1683
1684           notify = svn_wc_create_notify(local_abspath, svn_wc_notify_skip,
1685                                         scratch_pool);
1686           notify->kind = svn_node_file;
1687           notify->content_state = notify->prop_state = fb->skip_reason;
1688
1689           (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2,
1690                                         notify,
1691                                         scratch_pool);
1692         }
1693
1694       if (merge_b->merge_source.ancestral
1695           || merge_b->reintegrate_merge)
1696         {
1697           store_path(merge_b->skipped_abspaths, local_abspath);
1698         }
1699     }
1700   else if (fb->tree_conflict_reason != CONFLICT_REASON_NONE)
1701     {
1702       /* open_file() decided that a tree conflict should be raised */
1703
1704       SVN_ERR(record_tree_conflict(merge_b, local_abspath, fb->parent_baton,
1705                                    svn_node_file, fb->tree_conflict_action,
1706                                    fb->tree_conflict_reason,
1707                                    NULL, TRUE,
1708                                    scratch_pool));
1709     }
1710
1711   return SVN_NO_ERROR;
1712 }
1713
1714 /* An svn_diff_tree_processor_t function.
1715
1716    Called before either merge_file_changed(), merge_file_added(),
1717    merge_file_deleted() or merge_file_closed(), unless it sets *SKIP to TRUE.
1718
1719    When *SKIP is TRUE, the diff driver avoids work on getting the details
1720    for the closing callbacks.
1721  */
1722 static svn_error_t *
1723 merge_file_opened(void **new_file_baton,
1724                   svn_boolean_t *skip,
1725                   const char *relpath,
1726                   const svn_diff_source_t *left_source,
1727                   const svn_diff_source_t *right_source,
1728                   const svn_diff_source_t *copyfrom_source,
1729                   void *dir_baton,
1730                   const struct svn_diff_tree_processor_t *processor,
1731                   apr_pool_t *result_pool,
1732                   apr_pool_t *scratch_pool)
1733 {
1734   merge_cmd_baton_t *merge_b = processor->baton;
1735   struct merge_dir_baton_t *pdb = dir_baton;
1736   struct merge_file_baton_t *fb;
1737   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
1738                                               relpath, scratch_pool);
1739
1740   fb = apr_pcalloc(result_pool, sizeof(*fb));
1741   fb->tree_conflict_reason = CONFLICT_REASON_NONE;
1742   fb->tree_conflict_action = svn_wc_conflict_action_edit;
1743   fb->skip_reason = svn_wc_notify_state_unknown;
1744
1745   *new_file_baton = fb;
1746
1747   if (pdb)
1748     {
1749       fb->parent_baton = pdb;
1750       fb->shadowed = pdb->shadowed;
1751       fb->skip_reason = pdb->skip_reason;
1752     }
1753
1754   if (fb->shadowed)
1755     {
1756       /* An ancestor is tree conflicted. Nothing to do here. */
1757     }
1758   else if (left_source != NULL)
1759     {
1760       /* Node is expected to be a file, which will be changed or deleted. */
1761       svn_node_kind_t kind;
1762       svn_boolean_t is_deleted;
1763       svn_boolean_t excluded;
1764       svn_depth_t parent_depth;
1765
1766       if (! right_source)
1767         fb->tree_conflict_action = svn_wc_conflict_action_delete;
1768
1769       {
1770         svn_wc_notify_state_t obstr_state;
1771
1772         SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, &excluded,
1773                                           &kind, &parent_depth,
1774                                           merge_b, local_abspath,
1775                                           scratch_pool));
1776
1777         if (obstr_state != svn_wc_notify_state_inapplicable)
1778           {
1779             fb->shadowed = TRUE;
1780             fb->tree_conflict_reason = CONFLICT_REASON_SKIP;
1781             fb->skip_reason = obstr_state;
1782             return SVN_NO_ERROR;
1783           }
1784
1785         if (is_deleted)
1786           kind = svn_node_none;
1787       }
1788
1789       if (kind == svn_node_none)
1790         {
1791           fb->shadowed = TRUE;
1792
1793           /* If this is not the merge target and the parent is too shallow to
1794              contain this directory, and the directory is not present
1795              via exclusion or depth filtering, skip it instead of recording
1796              a tree conflict.
1797
1798              Non-inheritable mergeinfo will be recorded, allowing
1799              future merges into non-shallow working copies to merge
1800              changes we missed this time around. */
1801           if (pdb && (excluded
1802                       || (parent_depth != svn_depth_unknown &&
1803                           parent_depth < svn_depth_files)))
1804             {
1805                 fb->shadowed = TRUE;
1806
1807                 fb->tree_conflict_reason = CONFLICT_REASON_SKIP;
1808                 fb->skip_reason = svn_wc_notify_state_missing;
1809                 return SVN_NO_ERROR;
1810             }
1811
1812           if (is_deleted)
1813             fb->tree_conflict_reason = svn_wc_conflict_reason_deleted;
1814           else
1815             fb->tree_conflict_reason = svn_wc_conflict_reason_missing;
1816
1817           /* ### Similar to directory */
1818           *skip = TRUE;
1819           SVN_ERR(mark_file_edited(merge_b, fb, local_abspath, scratch_pool));
1820           return SVN_NO_ERROR;
1821           /* ### /Similar */
1822         }
1823       else if (kind != svn_node_file)
1824         {
1825           fb->shadowed = TRUE;
1826
1827           fb->tree_conflict_reason = svn_wc_conflict_reason_obstructed;
1828
1829           /* ### Similar to directory */
1830           *skip = TRUE;
1831           SVN_ERR(mark_file_edited(merge_b, fb, local_abspath, scratch_pool));
1832           return SVN_NO_ERROR;
1833           /* ### /Similar */
1834         }
1835
1836       if (! right_source)
1837         {
1838           /* We want to delete the directory */
1839           fb->tree_conflict_action = svn_wc_conflict_action_delete;
1840           SVN_ERR(mark_file_edited(merge_b, fb, local_abspath, scratch_pool));
1841
1842           if (fb->shadowed)
1843             {
1844               return SVN_NO_ERROR; /* Already set a tree conflict */
1845             }
1846
1847           /* Comparison mode to verify for delete tree conflicts? */
1848           if (pdb && pdb->delete_state
1849               && pdb->delete_state->found_edit)
1850             {
1851               /* Earlier nodes found a conflict. Done. */
1852               *skip = TRUE;
1853             }
1854         }
1855     }
1856   else
1857     {
1858       const svn_wc_conflict_description2_t *old_tc = NULL;
1859
1860       /* The node doesn't exist pre-merge: We have an addition */
1861       fb->added = TRUE;
1862       fb->tree_conflict_action = svn_wc_conflict_action_add;
1863
1864       if (pdb && pdb->pending_deletes
1865           && svn_hash_gets(pdb->pending_deletes, local_abspath))
1866         {
1867           fb->add_is_replace = TRUE;
1868           fb->tree_conflict_action = svn_wc_conflict_action_replace;
1869
1870           svn_hash_sets(pdb->pending_deletes, local_abspath, NULL);
1871         }
1872
1873       if (pdb
1874           && pdb->new_tree_conflicts
1875           && (old_tc = svn_hash_gets(pdb->new_tree_conflicts, local_abspath)))
1876         {
1877           fb->tree_conflict_action = svn_wc_conflict_action_replace;
1878           fb->tree_conflict_reason = old_tc->reason;
1879
1880           /* Update the tree conflict to store that this is a replace */
1881           SVN_ERR(record_tree_conflict(merge_b, local_abspath, pdb,
1882                                        svn_node_file,
1883                                        fb->tree_conflict_action,
1884                                        fb->tree_conflict_reason,
1885                                        old_tc, FALSE,
1886                                        scratch_pool));
1887
1888           if (old_tc->reason == svn_wc_conflict_reason_deleted
1889               || old_tc->reason == svn_wc_conflict_reason_moved_away)
1890             {
1891               /* Issue #3806: Incoming replacements on local deletes produce
1892                  inconsistent result.
1893
1894                  In this specific case we can continue applying the add part
1895                  of the replacement. */
1896             }
1897           else
1898             {
1899               *skip = TRUE;
1900
1901               return SVN_NO_ERROR;
1902             }
1903         }
1904       else if (! (merge_b->dry_run
1905                   && ((pdb && pdb->added) || fb->add_is_replace)))
1906         {
1907           svn_wc_notify_state_t obstr_state;
1908           svn_node_kind_t kind;
1909           svn_boolean_t is_deleted;
1910
1911           SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, NULL,
1912                                             &kind, NULL,
1913                                             merge_b, local_abspath,
1914                                             scratch_pool));
1915
1916           if (obstr_state != svn_wc_notify_state_inapplicable)
1917             {
1918               /* Skip the obstruction */
1919               fb->shadowed = TRUE;
1920               fb->tree_conflict_reason = CONFLICT_REASON_SKIP;
1921               fb->skip_reason = obstr_state;
1922             }
1923           else if (kind != svn_node_none && !is_deleted)
1924             {
1925               /* Set a tree conflict */
1926               fb->shadowed = TRUE;
1927               fb->tree_conflict_reason = svn_wc_conflict_reason_obstructed;
1928             }
1929         }
1930
1931       /* Handle pending conflicts */
1932       SVN_ERR(mark_file_edited(merge_b, fb, local_abspath, scratch_pool));
1933     }
1934
1935   return SVN_NO_ERROR;
1936 }
1937
1938 /* An svn_diff_tree_processor_t function.
1939  *
1940  * Called after merge_file_opened() when a node receives only text and/or
1941  * property changes between LEFT_SOURCE and RIGHT_SOURCE.
1942  *
1943  * left_file and right_file can be NULL when the file is not modified.
1944  * left_props and right_props are always available.
1945  */
1946 static svn_error_t *
1947 merge_file_changed(const char *relpath,
1948                   const svn_diff_source_t *left_source,
1949                   const svn_diff_source_t *right_source,
1950                   const char *left_file,
1951                   const char *right_file,
1952                   /*const*/ apr_hash_t *left_props,
1953                   /*const*/ apr_hash_t *right_props,
1954                   svn_boolean_t file_modified,
1955                   const apr_array_header_t *prop_changes,
1956                   void *file_baton,
1957                   const struct svn_diff_tree_processor_t *processor,
1958                   apr_pool_t *scratch_pool)
1959 {
1960   merge_cmd_baton_t *merge_b = processor->baton;
1961   struct merge_file_baton_t *fb = file_baton;
1962   svn_client_ctx_t *ctx = merge_b->ctx;
1963   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
1964                                               relpath, scratch_pool);
1965   const svn_wc_conflict_version_t *left;
1966   const svn_wc_conflict_version_t *right;
1967   svn_wc_notify_state_t text_state;
1968   svn_wc_notify_state_t property_state;
1969
1970   SVN_ERR_ASSERT(local_abspath && svn_dirent_is_absolute(local_abspath));
1971   SVN_ERR_ASSERT(!left_file || svn_dirent_is_absolute(left_file));
1972   SVN_ERR_ASSERT(!right_file || svn_dirent_is_absolute(right_file));
1973
1974   SVN_ERR(mark_file_edited(merge_b, fb, local_abspath, scratch_pool));
1975
1976   if (fb->shadowed)
1977     {
1978       if (fb->tree_conflict_reason == CONFLICT_REASON_NONE)
1979         {
1980           /* We haven't notified for this node yet: report a skip */
1981           SVN_ERR(record_skip(merge_b, local_abspath, svn_node_file,
1982                               svn_wc_notify_update_shadowed_update,
1983                               fb->skip_reason, fb->parent_baton,
1984                               scratch_pool));
1985         }
1986
1987       return SVN_NO_ERROR;
1988     }
1989
1990   /* This callback is essentially no more than a wrapper around
1991      svn_wc_merge5().  Thank goodness that all the
1992      diff-editor-mechanisms are doing the hard work of getting the
1993      fulltexts! */
1994
1995   property_state = svn_wc_notify_state_unchanged;
1996   text_state = svn_wc_notify_state_unchanged;
1997
1998   SVN_ERR(prepare_merge_props_changed(&prop_changes, local_abspath,
1999                                       prop_changes, merge_b,
2000                                       scratch_pool, scratch_pool));
2001
2002   SVN_ERR(make_conflict_versions(&left, &right, local_abspath,
2003                                  svn_node_file, &merge_b->merge_source, merge_b->target,
2004                                  scratch_pool, scratch_pool));
2005
2006   /* Do property merge now, if we are not going to perform a text merge */
2007   if ((merge_b->record_only || !left_file) && prop_changes->nelts)
2008     {
2009       SVN_ERR(svn_wc_merge_props3(&property_state, ctx->wc_ctx, local_abspath,
2010                                   left, right,
2011                                   left_props, prop_changes,
2012                                   merge_b->dry_run,
2013                                   NULL, NULL,
2014                                   ctx->cancel_func, ctx->cancel_baton,
2015                                   scratch_pool));
2016       if (property_state == svn_wc_notify_state_conflicted)
2017         {
2018           alloc_and_store_path(&merge_b->conflicted_paths, local_abspath,
2019                                merge_b->pool);
2020         }
2021     }
2022
2023   /* Easy out: We are only applying mergeinfo differences. */
2024   if (merge_b->record_only)
2025     {
2026       /* NO-OP */
2027     }
2028   else if (left_file)
2029     {
2030       svn_boolean_t has_local_mods;
2031       enum svn_wc_merge_outcome_t content_outcome;
2032       const char *target_label;
2033       const char *left_label;
2034       const char *right_label;
2035       const char *path_ext = "";
2036
2037       if (merge_b->ext_patterns && merge_b->ext_patterns->nelts)
2038         {
2039           svn_path_splitext(NULL, &path_ext, local_abspath, scratch_pool);
2040           if (! (*path_ext
2041                  && svn_cstring_match_glob_list(path_ext,
2042                                                 merge_b->ext_patterns)))
2043             {
2044               path_ext = "";
2045             }
2046         }
2047
2048       /* xgettext: the '.working', '.merge-left.r%ld' and
2049          '.merge-right.r%ld' strings are used to tag onto a file
2050          name in case of a merge conflict */
2051
2052       target_label = apr_psprintf(scratch_pool, _(".working%s%s"),
2053                                   *path_ext ? "." : "", path_ext);
2054       left_label = apr_psprintf(scratch_pool,
2055                                 _(".merge-left.r%ld%s%s"),
2056                                 left_source->revision,
2057                                 *path_ext ? "." : "", path_ext);
2058       right_label = apr_psprintf(scratch_pool,
2059                                  _(".merge-right.r%ld%s%s"),
2060                                  right_source->revision,
2061                                  *path_ext ? "." : "", path_ext);
2062
2063       SVN_ERR(svn_wc_text_modified_p2(&has_local_mods, ctx->wc_ctx,
2064                                       local_abspath, FALSE, scratch_pool));
2065
2066       /* Do property merge and text merge in one step so that keyword expansion
2067          takes into account the new property values. */
2068       SVN_ERR(svn_wc_merge5(&content_outcome, &property_state, ctx->wc_ctx,
2069                             left_file, right_file, local_abspath,
2070                             left_label, right_label, target_label,
2071                             left, right,
2072                             merge_b->dry_run, merge_b->diff3_cmd,
2073                             merge_b->merge_options,
2074                             left_props, prop_changes,
2075                             NULL, NULL,
2076                             ctx->cancel_func,
2077                             ctx->cancel_baton,
2078                             scratch_pool));
2079
2080       if (content_outcome == svn_wc_merge_conflict
2081           || property_state == svn_wc_notify_state_conflicted)
2082         {
2083           alloc_and_store_path(&merge_b->conflicted_paths, local_abspath,
2084                                merge_b->pool);
2085         }
2086
2087       if (content_outcome == svn_wc_merge_conflict)
2088         text_state = svn_wc_notify_state_conflicted;
2089       else if (has_local_mods
2090                && content_outcome != svn_wc_merge_unchanged)
2091         text_state = svn_wc_notify_state_merged;
2092       else if (content_outcome == svn_wc_merge_merged)
2093         text_state = svn_wc_notify_state_changed;
2094       else if (content_outcome == svn_wc_merge_no_merge)
2095         text_state = svn_wc_notify_state_missing;
2096       else /* merge_outcome == svn_wc_merge_unchanged */
2097         text_state = svn_wc_notify_state_unchanged;
2098     }
2099
2100   if (text_state == svn_wc_notify_state_conflicted
2101       || text_state == svn_wc_notify_state_merged
2102       || text_state == svn_wc_notify_state_changed
2103       || property_state == svn_wc_notify_state_conflicted
2104       || property_state == svn_wc_notify_state_merged
2105       || property_state == svn_wc_notify_state_changed)
2106     {
2107       SVN_ERR(record_update_update(merge_b, local_abspath, svn_node_file,
2108                                    text_state, property_state,
2109                                    scratch_pool));
2110     }
2111
2112   return SVN_NO_ERROR;
2113 }
2114
2115 /* An svn_diff_tree_processor_t function.
2116  *
2117  * Called after merge_file_opened() when a node doesn't exist in LEFT_SOURCE,
2118  * but does in RIGHT_SOURCE.
2119  *
2120  * When a node is replaced instead of just added a separate opened+deleted will
2121  * be invoked before the current open+added.
2122  */
2123 static svn_error_t *
2124 merge_file_added(const char *relpath,
2125                  const svn_diff_source_t *copyfrom_source,
2126                  const svn_diff_source_t *right_source,
2127                  const char *copyfrom_file,
2128                  const char *right_file,
2129                  /*const*/ apr_hash_t *copyfrom_props,
2130                  /*const*/ apr_hash_t *right_props,
2131                  void *file_baton,
2132                  const struct svn_diff_tree_processor_t *processor,
2133                  apr_pool_t *scratch_pool)
2134 {
2135   merge_cmd_baton_t *merge_b = processor->baton;
2136   struct merge_file_baton_t *fb = file_baton;
2137   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
2138                                               relpath, scratch_pool);
2139   apr_hash_t *pristine_props;
2140   apr_hash_t *new_props;
2141
2142   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
2143
2144   SVN_ERR(mark_file_edited(merge_b, fb, local_abspath, scratch_pool));
2145
2146   if (fb->shadowed)
2147     {
2148       if (fb->tree_conflict_reason == CONFLICT_REASON_NONE)
2149         {
2150           /* We haven't notified for this node yet: report a skip */
2151           SVN_ERR(record_skip(merge_b, local_abspath, svn_node_file,
2152                               svn_wc_notify_update_shadowed_add,
2153                               fb->skip_reason, fb->parent_baton,
2154                               scratch_pool));
2155         }
2156
2157       return SVN_NO_ERROR;
2158     }
2159
2160   /* Easy out: We are only applying mergeinfo differences. */
2161   if (merge_b->record_only)
2162     {
2163       return SVN_NO_ERROR;
2164     }
2165
2166   if ((merge_b->merge_source.ancestral || merge_b->reintegrate_merge)
2167       && ( !fb->parent_baton || !fb->parent_baton->added))
2168     {
2169       /* Store the roots of added subtrees */
2170       store_path(merge_b->added_abspaths, local_abspath);
2171     }
2172
2173   if (!merge_b->dry_run)
2174     {
2175       const char *copyfrom_url;
2176       svn_revnum_t copyfrom_rev;
2177       svn_stream_t *new_contents, *pristine_contents;
2178
2179       /* If this is a merge from the same repository as our
2180          working copy, we handle adds as add-with-history.
2181          Otherwise, we'll use a pure add. */
2182       if (merge_b->same_repos)
2183         {
2184           const char *child =
2185             svn_dirent_skip_ancestor(merge_b->target->abspath,
2186                                      local_abspath);
2187           SVN_ERR_ASSERT(child != NULL);
2188           copyfrom_url = svn_path_url_add_component2(
2189                                        merge_b->merge_source.loc2->url,
2190                                        child, scratch_pool);
2191           copyfrom_rev = right_source->revision;
2192           SVN_ERR(check_repos_match(merge_b->target, local_abspath,
2193                                     copyfrom_url, scratch_pool));
2194           SVN_ERR(svn_stream_open_readonly(&pristine_contents,
2195                                            right_file,
2196                                            scratch_pool,
2197                                            scratch_pool));
2198           new_contents = NULL; /* inherit from new_base_contents */
2199
2200           pristine_props = right_props; /* Includes last_* information */
2201           new_props = NULL; /* No local changes */
2202
2203           if (svn_hash_gets(pristine_props, SVN_PROP_MERGEINFO))
2204             {
2205               alloc_and_store_path(&merge_b->paths_with_new_mergeinfo,
2206                                    local_abspath, merge_b->pool);
2207             }
2208         }
2209       else
2210         {
2211           apr_array_header_t *regular_props;
2212
2213           copyfrom_url = NULL;
2214           copyfrom_rev = SVN_INVALID_REVNUM;
2215
2216           pristine_contents = svn_stream_empty(scratch_pool);
2217           SVN_ERR(svn_stream_open_readonly(&new_contents, right_file,
2218                                            scratch_pool, scratch_pool));
2219
2220           pristine_props = apr_hash_make(scratch_pool); /* Local addition */
2221
2222           /* We don't want any foreign properties */
2223           SVN_ERR(svn_categorize_props(svn_prop_hash_to_array(right_props,
2224                                                               scratch_pool),
2225                                        NULL, NULL, &regular_props,
2226                                        scratch_pool));
2227
2228           new_props = svn_prop_array_to_hash(regular_props, scratch_pool);
2229
2230           /* Issue #3383: We don't want mergeinfo from a foreign repository. */
2231           svn_hash_sets(new_props, SVN_PROP_MERGEINFO, NULL);
2232         }
2233
2234       /* Do everything like if we had called 'svn cp PATH1 PATH2'. */
2235       SVN_ERR(svn_wc_add_repos_file4(merge_b->ctx->wc_ctx,
2236                                       local_abspath,
2237                                       pristine_contents,
2238                                       new_contents,
2239                                       pristine_props, new_props,
2240                                       copyfrom_url, copyfrom_rev,
2241                                       merge_b->ctx->cancel_func,
2242                                       merge_b->ctx->cancel_baton,
2243                                       scratch_pool));
2244
2245       /* Caller must call svn_sleep_for_timestamps() */
2246       *merge_b->use_sleep = TRUE;
2247     }
2248
2249   SVN_ERR(record_update_add(merge_b, local_abspath, svn_node_file,
2250                             fb->add_is_replace, scratch_pool));
2251
2252   return SVN_NO_ERROR;
2253 }
2254
2255 /* Compare the two sets of properties PROPS1 and PROPS2, ignoring the
2256  * "svn:mergeinfo" property, and noticing only "normal" props. Set *SAME to
2257  * true if the rest of the properties are identical or false if they differ.
2258  */
2259 static svn_error_t *
2260 properties_same_p(svn_boolean_t *same,
2261                   apr_hash_t *props1,
2262                   apr_hash_t *props2,
2263                   apr_pool_t *scratch_pool)
2264 {
2265   apr_array_header_t *prop_changes;
2266   int i, diffs;
2267
2268   /* Examine the properties that differ */
2269   SVN_ERR(svn_prop_diffs(&prop_changes, props1, props2, scratch_pool));
2270   diffs = 0;
2271   for (i = 0; i < prop_changes->nelts; i++)
2272     {
2273       const char *pname = APR_ARRAY_IDX(prop_changes, i, svn_prop_t).name;
2274
2275       /* Count the properties we're interested in; ignore the rest */
2276       if (svn_wc_is_normal_prop(pname)
2277           && strcmp(pname, SVN_PROP_MERGEINFO) != 0)
2278         diffs++;
2279     }
2280   *same = (diffs == 0);
2281   return SVN_NO_ERROR;
2282 }
2283
2284 /* Compare the file OLDER_ABSPATH (together with its normal properties in
2285  * ORIGINAL_PROPS which may also contain WC props and entry props) with the
2286  * versioned file MINE_ABSPATH (together with its versioned properties).
2287  * Set *SAME to true if they are the same or false if they differ, ignoring
2288  * the "svn:mergeinfo" property, and ignoring differences in keyword
2289  * expansion and end-of-line style. */
2290 static svn_error_t *
2291 files_same_p(svn_boolean_t *same,
2292              const char *older_abspath,
2293              apr_hash_t *original_props,
2294              const char *mine_abspath,
2295              svn_wc_context_t *wc_ctx,
2296              apr_pool_t *scratch_pool)
2297 {
2298   apr_hash_t *working_props;
2299
2300   SVN_ERR(svn_wc_prop_list2(&working_props, wc_ctx, mine_abspath,
2301                             scratch_pool, scratch_pool));
2302
2303   /* Compare the properties */
2304   SVN_ERR(properties_same_p(same, original_props, working_props,
2305                             scratch_pool));
2306   if (*same)
2307     {
2308       svn_stream_t *mine_stream;
2309       svn_stream_t *older_stream;
2310       svn_opt_revision_t working_rev = { svn_opt_revision_working, { 0 } };
2311
2312       /* Compare the file content, translating 'mine' to 'normal' form. */
2313       if (svn_prop_get_value(working_props, SVN_PROP_SPECIAL) != NULL)
2314         SVN_ERR(svn_subst_read_specialfile(&mine_stream, mine_abspath,
2315                                            scratch_pool, scratch_pool));
2316       else
2317         SVN_ERR(svn_client__get_normalized_stream(&mine_stream, wc_ctx,
2318                                                   mine_abspath, &working_rev,
2319                                                   FALSE, TRUE, NULL, NULL,
2320                                                   scratch_pool, scratch_pool));
2321
2322       SVN_ERR(svn_stream_open_readonly(&older_stream, older_abspath,
2323                                        scratch_pool, scratch_pool));
2324
2325       SVN_ERR(svn_stream_contents_same2(same, mine_stream, older_stream,
2326                                         scratch_pool));
2327
2328     }
2329
2330   return SVN_NO_ERROR;
2331 }
2332
2333 /* An svn_diff_tree_processor_t function.
2334  *
2335  * Called after merge_file_opened() when a node does exist in LEFT_SOURCE, but
2336  * no longer exists (or is replaced) in RIGHT_SOURCE.
2337  *
2338  * When a node is replaced instead of just added a separate opened+added will
2339  * be invoked after the current open+deleted.
2340  */
2341 static svn_error_t *
2342 merge_file_deleted(const char *relpath,
2343                    const svn_diff_source_t *left_source,
2344                    const char *left_file,
2345                    /*const*/ apr_hash_t *left_props,
2346                    void *file_baton,
2347                    const struct svn_diff_tree_processor_t *processor,
2348                    apr_pool_t *scratch_pool)
2349 {
2350   merge_cmd_baton_t *merge_b = processor->baton;
2351   struct merge_file_baton_t *fb = file_baton;
2352   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
2353                                               relpath, scratch_pool);
2354   svn_boolean_t same;
2355
2356   SVN_ERR(mark_file_edited(merge_b, fb, local_abspath, scratch_pool));
2357
2358   if (fb->shadowed)
2359     {
2360       if (fb->tree_conflict_reason == CONFLICT_REASON_NONE)
2361         {
2362           /* We haven't notified for this node yet: report a skip */
2363           SVN_ERR(record_skip(merge_b, local_abspath, svn_node_file,
2364                               svn_wc_notify_update_shadowed_delete,
2365                               fb->skip_reason, fb->parent_baton,
2366                               scratch_pool));
2367         }
2368
2369       return SVN_NO_ERROR;
2370     }
2371
2372   /* Easy out: We are only applying mergeinfo differences. */
2373   if (merge_b->record_only)
2374     {
2375       return SVN_NO_ERROR;
2376     }
2377
2378   /* If the files are identical, attempt deletion */
2379   if (merge_b->force_delete)
2380     same = TRUE;
2381   else
2382     SVN_ERR(files_same_p(&same, left_file, left_props,
2383                          local_abspath, merge_b->ctx->wc_ctx,
2384                          scratch_pool));
2385
2386   if (fb->parent_baton
2387       && fb->parent_baton->delete_state)
2388     {
2389       if (same)
2390         {
2391           /* Note that we checked this file */
2392           store_path(fb->parent_baton->delete_state->compared_abspaths,
2393                      local_abspath);
2394         }
2395       else
2396         {
2397           /* We found some modification. Parent should raise a tree conflict */
2398           fb->parent_baton->delete_state->found_edit = TRUE;
2399         }
2400
2401       return SVN_NO_ERROR;
2402     }
2403   else if (same)
2404     {
2405       if (!merge_b->dry_run)
2406         SVN_ERR(svn_wc_delete4(merge_b->ctx->wc_ctx, local_abspath,
2407                                FALSE /* keep_local */, FALSE /* unversioned */,
2408                                merge_b->ctx->cancel_func,
2409                                merge_b->ctx->cancel_baton,
2410                                NULL, NULL /* no notify */,
2411                                scratch_pool));
2412
2413       /* Record that we might have deleted mergeinfo */
2414       alloc_and_store_path(&merge_b->paths_with_deleted_mergeinfo,
2415                            local_abspath, merge_b->pool);
2416
2417       /* And notify the deletion */
2418       SVN_ERR(record_update_delete(merge_b, fb->parent_baton, local_abspath,
2419                                    svn_node_file, scratch_pool));
2420     }
2421   else
2422     {
2423       /* The files differ, so raise a conflict instead of deleting */
2424
2425       /* This is use case 5 described in the paper attached to issue
2426        * #2282.  See also notes/tree-conflicts/detection.txt
2427        */
2428       SVN_ERR(record_tree_conflict(merge_b, local_abspath, fb->parent_baton,
2429                                    svn_node_file,
2430                                    svn_wc_conflict_action_delete,
2431                                    svn_wc_conflict_reason_edited,
2432                                    NULL, TRUE,
2433                                    scratch_pool));
2434     }
2435
2436   return SVN_NO_ERROR;
2437 }
2438
2439 /* An svn_diff_tree_processor_t function.
2440
2441    Called before either merge_dir_changed(), merge_dir_added(),
2442    merge_dir_deleted() or merge_dir_closed(), unless it sets *SKIP to TRUE.
2443
2444    After this call and before the close call, all descendants will receive
2445    their changes, unless *SKIP_CHILDREN is set to TRUE.
2446
2447    When *SKIP is TRUE, the diff driver avoids work on getting the details
2448    for the closing callbacks.
2449
2450    The SKIP and SKIP_DESCENDANTS work independantly.
2451  */
2452 static svn_error_t *
2453 merge_dir_opened(void **new_dir_baton,
2454                  svn_boolean_t *skip,
2455                  svn_boolean_t *skip_children,
2456                  const char *relpath,
2457                  const svn_diff_source_t *left_source,
2458                  const svn_diff_source_t *right_source,
2459                  const svn_diff_source_t *copyfrom_source,
2460                  void *parent_dir_baton,
2461                  const struct svn_diff_tree_processor_t *processor,
2462                  apr_pool_t *result_pool,
2463                  apr_pool_t *scratch_pool)
2464 {
2465   merge_cmd_baton_t *merge_b = processor->baton;
2466   struct merge_dir_baton_t *db;
2467   struct merge_dir_baton_t *pdb = parent_dir_baton;
2468
2469   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
2470                                               relpath, scratch_pool);
2471
2472   db = apr_pcalloc(result_pool, sizeof(*db));
2473   db->pool = result_pool;
2474   db->tree_conflict_reason = CONFLICT_REASON_NONE;
2475   db->tree_conflict_action = svn_wc_conflict_action_edit;
2476   db->skip_reason = svn_wc_notify_state_unknown;
2477
2478   *new_dir_baton = db;
2479
2480   if (pdb)
2481     {
2482       db->parent_baton = pdb;
2483       db->shadowed = pdb->shadowed;
2484       db->skip_reason = pdb->skip_reason;
2485     }
2486
2487   if (db->shadowed)
2488     {
2489       /* An ancestor is tree conflicted. Nothing to do here. */
2490       if (! left_source)
2491         db->added = TRUE;
2492     }
2493   else if (left_source != NULL)
2494     {
2495       /* Node is expected to be a directory. */
2496       svn_node_kind_t kind;
2497       svn_boolean_t is_deleted;
2498       svn_boolean_t excluded;
2499       svn_depth_t parent_depth;
2500
2501       if (! right_source)
2502           db->tree_conflict_action = svn_wc_conflict_action_delete;
2503
2504       /* Check for an obstructed or missing node on disk. */
2505       {
2506         svn_wc_notify_state_t obstr_state;
2507         SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, &excluded,
2508                                           &kind, &parent_depth,
2509                                           merge_b, local_abspath,
2510                                           scratch_pool));
2511
2512         if (obstr_state != svn_wc_notify_state_inapplicable)
2513           {
2514             db->shadowed = TRUE;
2515
2516             if (obstr_state == svn_wc_notify_state_obstructed)
2517               {
2518                 svn_boolean_t is_wcroot;
2519
2520                 SVN_ERR(svn_wc_check_root(&is_wcroot, NULL, NULL,
2521                                         merge_b->ctx->wc_ctx,
2522                                         local_abspath, scratch_pool));
2523
2524                 if (is_wcroot)
2525                   {
2526                     db->tree_conflict_reason = CONFLICT_REASON_SKIP_WC;
2527                     return SVN_NO_ERROR;
2528                   }
2529               }
2530
2531             db->tree_conflict_reason = CONFLICT_REASON_SKIP;
2532             db->skip_reason = obstr_state;
2533
2534             if (! right_source)
2535               {
2536                 *skip = *skip_children = TRUE;
2537                 SVN_ERR(mark_dir_edited(merge_b, db, local_abspath,
2538                                         scratch_pool));
2539               }
2540
2541             return SVN_NO_ERROR;
2542           }
2543
2544         if (is_deleted)
2545           kind = svn_node_none;
2546       }
2547
2548       if (kind == svn_node_none)
2549         {
2550           db->shadowed = TRUE;
2551
2552           /* If this is not the merge target and the parent is too shallow to
2553              contain this directory, and the directory is not presen
2554              via exclusion or depth filtering, skip it instead of recording
2555              a tree conflict.
2556
2557              Non-inheritable mergeinfo will be recorded, allowing
2558              future merges into non-shallow working copies to merge
2559              changes we missed this time around. */
2560           if (pdb && (excluded
2561                       || (parent_depth != svn_depth_unknown &&
2562                           parent_depth < svn_depth_immediates)))
2563             {
2564               db->shadowed = TRUE;
2565
2566               db->tree_conflict_reason = CONFLICT_REASON_SKIP;
2567               db->skip_reason = svn_wc_notify_state_missing;
2568
2569               return SVN_NO_ERROR;
2570             }
2571
2572           if (is_deleted)
2573             db->tree_conflict_reason = svn_wc_conflict_reason_deleted;
2574           else
2575             db->tree_conflict_reason = svn_wc_conflict_reason_missing;
2576
2577           /* ### To avoid breaking tests */
2578           *skip = TRUE;
2579           *skip_children = TRUE;
2580           SVN_ERR(mark_dir_edited(merge_b, db, local_abspath, scratch_pool));
2581           return SVN_NO_ERROR;
2582           /* ### /avoid breaking tests */
2583         }
2584       else if (kind != svn_node_dir)
2585         {
2586           db->shadowed = TRUE;
2587
2588           db->tree_conflict_reason = svn_wc_conflict_reason_obstructed;
2589
2590           /* ### To avoid breaking tests */
2591           *skip = TRUE;
2592           *skip_children = TRUE;
2593           SVN_ERR(mark_dir_edited(merge_b, db, local_abspath, scratch_pool));
2594           return SVN_NO_ERROR;
2595           /* ### /avoid breaking tests */
2596         }
2597
2598       if (! right_source)
2599         {
2600           /* We want to delete the directory */
2601           /* Mark PB edited now? */
2602           db->tree_conflict_action = svn_wc_conflict_action_delete;
2603           SVN_ERR(mark_dir_edited(merge_b, db, local_abspath, scratch_pool));
2604
2605           if (db->shadowed)
2606             {
2607               *skip_children = TRUE;
2608               return SVN_NO_ERROR; /* Already set a tree conflict */
2609             }
2610
2611           db->delete_state = (pdb != NULL) ? pdb->delete_state : NULL;
2612
2613           if (db->delete_state && db->delete_state->found_edit)
2614             {
2615               /* A sibling found a conflict. Done. */
2616               *skip = TRUE;
2617               *skip_children = TRUE;
2618             }
2619           else if (merge_b->force_delete)
2620             {
2621               /* No comparison necessary */
2622               *skip_children = TRUE;
2623             }
2624           else if (! db->delete_state)
2625             {
2626               /* Start descendant comparison */
2627               db->delete_state = apr_pcalloc(db->pool,
2628                                              sizeof(*db->delete_state));
2629
2630               db->delete_state->del_root = db;
2631               db->delete_state->compared_abspaths = apr_hash_make(db->pool);
2632             }
2633         }
2634     }
2635   else
2636     {
2637       const svn_wc_conflict_description2_t *old_tc = NULL;
2638
2639       /* The node doesn't exist pre-merge: We have an addition */
2640       db->added = TRUE;
2641       db->tree_conflict_action = svn_wc_conflict_action_add;
2642
2643       if (pdb && pdb->pending_deletes
2644           && svn_hash_gets(pdb->pending_deletes, local_abspath))
2645         {
2646           db->add_is_replace = TRUE;
2647           db->tree_conflict_action = svn_wc_conflict_action_replace;
2648
2649           svn_hash_sets(pdb->pending_deletes, local_abspath, NULL);
2650         }
2651
2652       if (pdb
2653           && pdb->new_tree_conflicts
2654           && (old_tc = svn_hash_gets(pdb->new_tree_conflicts, local_abspath)))
2655         {
2656           db->tree_conflict_action = svn_wc_conflict_action_replace;
2657           db->tree_conflict_reason = old_tc->reason;
2658
2659           if (old_tc->reason == svn_wc_conflict_reason_deleted
2660              || old_tc->reason == svn_wc_conflict_reason_moved_away)
2661             {
2662               /* Issue #3806: Incoming replacements on local deletes produce
2663                  inconsistent result.
2664
2665                  In this specific case we can continue applying the add part
2666                  of the replacement. */
2667             }
2668           else
2669             {
2670               *skip = TRUE;
2671               *skip_children = TRUE;
2672
2673               /* Update the tree conflict to store that this is a replace */
2674               SVN_ERR(record_tree_conflict(merge_b, local_abspath, pdb,
2675                                            svn_node_dir,
2676                                            db->tree_conflict_action,
2677                                            db->tree_conflict_reason,
2678                                            old_tc, FALSE,
2679                                            scratch_pool));
2680
2681               return SVN_NO_ERROR;
2682             }
2683         }
2684
2685       if (! (merge_b->dry_run
2686              && ((pdb && pdb->added) || db->add_is_replace)))
2687         {
2688           svn_wc_notify_state_t obstr_state;
2689           svn_node_kind_t kind;
2690           svn_boolean_t is_deleted;
2691
2692           SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, NULL,
2693                                             &kind, NULL,
2694                                             merge_b, local_abspath,
2695                                             scratch_pool));
2696
2697           /* In this case of adding a directory, we have an exception to the
2698            * usual "skip if it's inconsistent" rule. If the directory exists
2699            * on disk unexpectedly, we simply make it versioned, because we can
2700            * do so without risk of destroying data. Only skip if it is
2701            * versioned but unexpectedly missing from disk, or is unversioned
2702            * but obstructed by a node of the wrong kind. */
2703           if (obstr_state == svn_wc_notify_state_obstructed
2704               && (is_deleted || kind == svn_node_none))
2705             {
2706               svn_node_kind_t disk_kind;
2707
2708               SVN_ERR(svn_io_check_path(local_abspath, &disk_kind,
2709                                         scratch_pool));
2710
2711               if (disk_kind == svn_node_dir)
2712                 {
2713                   obstr_state = svn_wc_notify_state_inapplicable;
2714                   db->add_existing = TRUE; /* Take over existing directory */
2715                 }
2716             }
2717
2718           if (obstr_state != svn_wc_notify_state_inapplicable)
2719             {
2720               /* Skip the obstruction */
2721               db->shadowed = TRUE;
2722               db->tree_conflict_reason = CONFLICT_REASON_SKIP;
2723               db->skip_reason = obstr_state;
2724             }
2725           else if (kind != svn_node_none && !is_deleted)
2726             {
2727               /* Set a tree conflict */
2728               db->shadowed = TRUE;
2729               db->tree_conflict_reason = svn_wc_conflict_reason_obstructed;
2730
2731               if ((merge_b->merge_source.ancestral || merge_b->reintegrate_merge)
2732                   && !(pdb && pdb->shadowed))
2733                 {
2734                   store_path(merge_b->skipped_abspaths, local_abspath);
2735                 }
2736             }
2737         }
2738
2739       /* Handle pending conflicts */
2740       SVN_ERR(mark_dir_edited(merge_b, db, local_abspath, scratch_pool));
2741
2742       if (db->shadowed)
2743         {
2744           /* Notified and done. Skip children? */
2745         }
2746       else if (merge_b->record_only)
2747         {
2748           /* Ok, we are done for this node and its descendants */
2749           *skip = TRUE;
2750           *skip_children = TRUE;
2751         }
2752       else if (! merge_b->dry_run)
2753         {
2754           /* Create the directory on disk, to allow descendants to be added */
2755           if (! db->add_existing)
2756             SVN_ERR(svn_io_dir_make(local_abspath, APR_OS_DEFAULT,
2757                                     scratch_pool));
2758
2759           if (old_tc)
2760             {
2761               /* svn_wc_add4 and svn_wc_add_from_disk2 can't add a node
2762                  over an existing tree conflict */
2763
2764               /* ### These functions should take some tree conflict argument
2765                      and allow overwriting the tc when one is passed */
2766
2767               SVN_ERR(svn_wc__del_tree_conflict(merge_b->ctx->wc_ctx,
2768                                                 local_abspath,
2769                                                 scratch_pool));
2770             }
2771
2772           if (merge_b->same_repos)
2773             {
2774               const char *original_url;
2775
2776               original_url = svn_path_url_add_component2(
2777                                         merge_b->merge_source.loc2->url,
2778                                         relpath, scratch_pool);
2779
2780               /* Limitation (aka HACK):
2781                  We create a newly added directory with an original URL and
2782                  revision as that in the repository, but without its properties
2783                  and children.
2784
2785                  When the merge is cancelled before the final dir_added(), the
2786                  copy won't really represent the in-repository state of the node.
2787                */
2788               SVN_ERR(svn_wc_add4(merge_b->ctx->wc_ctx, local_abspath,
2789                                   svn_depth_infinity,
2790                                   original_url,
2791                                   right_source->revision,
2792                                   merge_b->ctx->cancel_func,
2793                                   merge_b->ctx->cancel_baton,
2794                                   NULL, NULL /* no notify! */,
2795                                   scratch_pool));
2796             }
2797           else
2798             {
2799               SVN_ERR(svn_wc_add_from_disk2(merge_b->ctx->wc_ctx, local_abspath,
2800                                             apr_hash_make(scratch_pool),
2801                                             NULL, NULL /* no notify! */,
2802                                             scratch_pool));
2803             }
2804
2805           if (old_tc != NULL)
2806             {
2807               /* ### Should be atomic with svn_wc_add(4|_from_disk2)() */
2808               SVN_ERR(record_tree_conflict(merge_b, local_abspath, pdb,
2809                                            svn_node_dir,
2810                                            db->tree_conflict_action,
2811                                            db->tree_conflict_reason,
2812                                            old_tc, FALSE,
2813                                            scratch_pool));
2814             }
2815         }
2816
2817       if (! db->shadowed && !merge_b->record_only)
2818         SVN_ERR(record_update_add(merge_b, local_abspath, svn_node_dir,
2819                                   db->add_is_replace, scratch_pool));
2820     }
2821   return SVN_NO_ERROR;
2822 }
2823
2824 /* An svn_diff_tree_processor_t function.
2825  *
2826  * Called after merge_dir_opened() when a node exists in both the left and
2827  * right source, but has its properties changed inbetween.
2828  *
2829  * After the merge_dir_opened() but before the call to this merge_dir_changed()
2830  * function all descendants will have been updated.
2831  */
2832 static svn_error_t *
2833 merge_dir_changed(const char *relpath,
2834                   const svn_diff_source_t *left_source,
2835                   const svn_diff_source_t *right_source,
2836                   /*const*/ apr_hash_t *left_props,
2837                   /*const*/ apr_hash_t *right_props,
2838                   const apr_array_header_t *prop_changes,
2839                   void *dir_baton,
2840                   const struct svn_diff_tree_processor_t *processor,
2841                   apr_pool_t *scratch_pool)
2842 {
2843   merge_cmd_baton_t *merge_b = processor->baton;
2844   struct merge_dir_baton_t *db = dir_baton;
2845   const apr_array_header_t *props;
2846   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
2847                                               relpath, scratch_pool);
2848
2849   SVN_ERR(handle_pending_notifications(merge_b, db, scratch_pool));
2850
2851   SVN_ERR(mark_dir_edited(merge_b, db, local_abspath, scratch_pool));
2852
2853   if (db->shadowed)
2854     {
2855       if (db->tree_conflict_reason == CONFLICT_REASON_NONE)
2856         {
2857           /* We haven't notified for this node yet: report a skip */
2858           SVN_ERR(record_skip(merge_b, local_abspath, svn_node_dir,
2859                               svn_wc_notify_update_shadowed_update,
2860                               db->skip_reason, db->parent_baton,
2861                               scratch_pool));
2862         }
2863
2864       return SVN_NO_ERROR;
2865     }
2866
2867   SVN_ERR(prepare_merge_props_changed(&props, local_abspath, prop_changes,
2868                                       merge_b, scratch_pool, scratch_pool));
2869
2870   if (props->nelts)
2871     {
2872       const svn_wc_conflict_version_t *left;
2873       const svn_wc_conflict_version_t *right;
2874       svn_client_ctx_t *ctx = merge_b->ctx;
2875       svn_wc_notify_state_t prop_state;
2876
2877       SVN_ERR(make_conflict_versions(&left, &right, local_abspath,
2878                                      svn_node_dir, &merge_b->merge_source,
2879                                      merge_b->target,
2880                                      scratch_pool, scratch_pool));
2881
2882       SVN_ERR(svn_wc_merge_props3(&prop_state, ctx->wc_ctx, local_abspath,
2883                                   left, right,
2884                                   left_props, props,
2885                                   merge_b->dry_run,
2886                                   NULL, NULL,
2887                                   ctx->cancel_func, ctx->cancel_baton,
2888                                   scratch_pool));
2889
2890       if (prop_state == svn_wc_notify_state_conflicted)
2891         {
2892           alloc_and_store_path(&merge_b->conflicted_paths, local_abspath,
2893                                merge_b->pool);
2894         }
2895
2896       if (prop_state == svn_wc_notify_state_conflicted
2897           || prop_state == svn_wc_notify_state_merged
2898           || prop_state == svn_wc_notify_state_changed)
2899         {
2900           SVN_ERR(record_update_update(merge_b, local_abspath, svn_node_file,
2901                                        svn_wc_notify_state_inapplicable,
2902                                        prop_state, scratch_pool));
2903         }
2904     }
2905
2906   return SVN_NO_ERROR;
2907 }
2908
2909
2910 /* An svn_diff_tree_processor_t function.
2911  *
2912  * Called after merge_dir_opened() when a node doesn't exist in LEFT_SOURCE,
2913  * but does in RIGHT_SOURCE. After the merge_dir_opened() but before the call
2914  * to this merge_dir_added() function all descendants will have been added.
2915  *
2916  * When a node is replaced instead of just added a separate opened+deleted will
2917  * be invoked before the current open+added.
2918  */
2919 static svn_error_t *
2920 merge_dir_added(const char *relpath,
2921                 const svn_diff_source_t *copyfrom_source,
2922                 const svn_diff_source_t *right_source,
2923                 /*const*/ apr_hash_t *copyfrom_props,
2924                 /*const*/ apr_hash_t *right_props,
2925                 void *dir_baton,
2926                 const struct svn_diff_tree_processor_t *processor,
2927                 apr_pool_t *scratch_pool)
2928 {
2929   merge_cmd_baton_t *merge_b = processor->baton;
2930   struct merge_dir_baton_t *db = dir_baton;
2931   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
2932                                               relpath, scratch_pool);
2933
2934   /* For consistency; usually a no-op from _dir_added() */
2935   SVN_ERR(handle_pending_notifications(merge_b, db, scratch_pool));
2936   SVN_ERR(mark_dir_edited(merge_b, db, local_abspath, scratch_pool));
2937
2938   if (db->shadowed)
2939     {
2940       if (db->tree_conflict_reason == CONFLICT_REASON_NONE)
2941         {
2942           /* We haven't notified for this node yet: report a skip */
2943           SVN_ERR(record_skip(merge_b, local_abspath, svn_node_dir,
2944                               svn_wc_notify_update_shadowed_add,
2945                               db->skip_reason, db->parent_baton,
2946                               scratch_pool));
2947         }
2948
2949       return SVN_NO_ERROR;
2950     }
2951
2952   SVN_ERR_ASSERT(
2953                  db->edited                  /* Marked edited from merge_open_dir() */
2954                  && ! merge_b->record_only /* Skip details from merge_open_dir() */
2955                  );
2956
2957   if ((merge_b->merge_source.ancestral || merge_b->reintegrate_merge)
2958       && ( !db->parent_baton || !db->parent_baton->added))
2959     {
2960       /* Store the roots of added subtrees */
2961       store_path(merge_b->added_abspaths, local_abspath);
2962     }
2963
2964   if (merge_b->same_repos)
2965     {
2966       /* When the directory was added in merge_dir_added() we didn't update its
2967          pristine properties. Instead we receive the property changes later and
2968          apply them in this function.
2969
2970          If we would apply them as changes (such as before fixing issue #3405),
2971          we would see the unmodified properties as local changes, and the
2972          pristine properties would be out of sync with what the repository
2973          expects for this directory.
2974
2975          Instead of doing that we now simply set the properties as the pristine
2976          properties via a private libsvn_wc api.
2977       */
2978
2979       const char *copyfrom_url;
2980       svn_revnum_t copyfrom_rev;
2981       const char *parent_abspath;
2982       const char *child;
2983
2984       /* Creating a hash containing regular and entry props */
2985       apr_hash_t *new_pristine_props = right_props;
2986
2987       parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
2988       child = svn_dirent_is_child(merge_b->target->abspath, local_abspath, NULL);
2989       SVN_ERR_ASSERT(child != NULL);
2990
2991       copyfrom_url = svn_path_url_add_component2(merge_b->merge_source.loc2->url,
2992                                                  child, scratch_pool);
2993       copyfrom_rev = right_source->revision;
2994
2995       SVN_ERR(check_repos_match(merge_b->target, parent_abspath, copyfrom_url,
2996                                 scratch_pool));
2997
2998       if (!merge_b->dry_run)
2999         {
3000           SVN_ERR(svn_wc__complete_directory_add(merge_b->ctx->wc_ctx,
3001                                                 local_abspath,
3002                                                 new_pristine_props,
3003                                                 copyfrom_url, copyfrom_rev,
3004                                                 scratch_pool));
3005         }
3006
3007       if (svn_hash_gets(new_pristine_props, SVN_PROP_MERGEINFO))
3008         {
3009           alloc_and_store_path(&merge_b->paths_with_new_mergeinfo,
3010                                local_abspath, merge_b->pool);
3011         }
3012     }
3013   else
3014     {
3015       apr_array_header_t *regular_props;
3016       apr_hash_t *new_props;
3017       svn_wc_notify_state_t prop_state;
3018
3019       SVN_ERR(svn_categorize_props(svn_prop_hash_to_array(right_props,
3020                                                           scratch_pool),
3021                                    NULL, NULL, &regular_props, scratch_pool));
3022
3023       new_props = svn_prop_array_to_hash(regular_props, scratch_pool);
3024
3025       svn_hash_sets(new_props, SVN_PROP_MERGEINFO, NULL);
3026
3027       /* ### What is the easiest way to set new_props on LOCAL_ABSPATH?
3028
3029          ### This doesn't need a merge as we just added the node
3030          ### (or installed a tree conflict and skipped this node)*/
3031
3032       SVN_ERR(svn_wc_merge_props3(&prop_state, merge_b->ctx->wc_ctx,
3033                                   local_abspath,
3034                                   NULL, NULL,
3035                                   apr_hash_make(scratch_pool),
3036                                   svn_prop_hash_to_array(new_props,
3037                                                          scratch_pool),
3038                                   merge_b->dry_run,
3039                                   NULL, NULL,
3040                                   merge_b->ctx->cancel_func,
3041                                   merge_b->ctx->cancel_baton,
3042                                   scratch_pool));
3043       if (prop_state == svn_wc_notify_state_conflicted)
3044         {
3045           alloc_and_store_path(&merge_b->conflicted_paths, local_abspath,
3046                                merge_b->pool);
3047         }
3048     }
3049
3050   return SVN_NO_ERROR;
3051 }
3052
3053 /* Helper for merge_dir_deleted. Implement svn_wc_status_func4_t */
3054 static svn_error_t *
3055 verify_touched_by_del_check(void *baton,
3056                             const char *local_abspath,
3057                             const svn_wc_status3_t *status,
3058                             apr_pool_t *scratch_pool)
3059 {
3060   struct dir_delete_baton_t *delb = baton;
3061
3062   if (svn_hash_gets(delb->compared_abspaths, local_abspath))
3063     return SVN_NO_ERROR;
3064
3065   switch (status->node_status)
3066     {
3067       case svn_wc_status_deleted:
3068       case svn_wc_status_ignored:
3069       case svn_wc_status_none:
3070         return SVN_NO_ERROR;
3071
3072       default:
3073         delb->found_edit = TRUE;
3074         return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
3075     }
3076 }
3077
3078 /* An svn_diff_tree_processor_t function.
3079  *
3080  * Called after merge_dir_opened() when a node existed only in the left source.
3081  *
3082  * After the merge_dir_opened() but before the call to this merge_dir_deleted()
3083  * function all descendants that existed in left_source will have been deleted.
3084  *
3085  * If this node is replaced, an _opened() followed by a matching _add() will
3086  * be invoked after this function.
3087  */
3088 static svn_error_t *
3089 merge_dir_deleted(const char *relpath,
3090                   const svn_diff_source_t *left_source,
3091                   /*const*/ apr_hash_t *left_props,
3092                   void *dir_baton,
3093                   const struct svn_diff_tree_processor_t *processor,
3094                   apr_pool_t *scratch_pool)
3095 {
3096   merge_cmd_baton_t *merge_b = processor->baton;
3097   struct merge_dir_baton_t *db = dir_baton;
3098   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
3099                                               relpath, scratch_pool);
3100   svn_boolean_t same;
3101   apr_hash_t *working_props;
3102
3103   SVN_ERR(handle_pending_notifications(merge_b, db, scratch_pool));
3104   SVN_ERR(mark_dir_edited(merge_b, db, local_abspath, scratch_pool));
3105
3106   if (db->shadowed)
3107     {
3108       if (db->tree_conflict_reason == CONFLICT_REASON_NONE)
3109         {
3110           /* We haven't notified for this node yet: report a skip */
3111           SVN_ERR(record_skip(merge_b, local_abspath, svn_node_dir,
3112                               svn_wc_notify_update_shadowed_delete,
3113                               db->skip_reason, db->parent_baton,
3114                               scratch_pool));
3115         }
3116
3117       return SVN_NO_ERROR;
3118     }
3119
3120   /* Easy out: We are only applying mergeinfo differences. */
3121   if (merge_b->record_only)
3122     {
3123       return SVN_NO_ERROR;
3124     }
3125
3126   SVN_ERR(svn_wc_prop_list2(&working_props,
3127                             merge_b->ctx->wc_ctx, local_abspath,
3128                             scratch_pool, scratch_pool));
3129
3130   if (merge_b->force_delete)
3131     {
3132       /* In this legacy mode we just assume that a directory delete
3133          matches any directory. db->delete_state is NULL */
3134       same = TRUE;
3135     }
3136   else
3137     {
3138       struct dir_delete_baton_t *delb;
3139
3140       /* Compare the properties */
3141       SVN_ERR(properties_same_p(&same, left_props, working_props,
3142                                 scratch_pool));
3143       delb = db->delete_state;
3144       assert(delb != NULL);
3145
3146       if (! same)
3147         {
3148           delb->found_edit = TRUE;
3149         }
3150       else
3151         {
3152           store_path(delb->compared_abspaths, local_abspath);
3153         }
3154
3155       if (delb->del_root != db)
3156         return SVN_NO_ERROR;
3157
3158       if (delb->found_edit)
3159         same = FALSE;
3160       else
3161         {
3162           apr_array_header_t *ignores;
3163           svn_error_t *err;
3164           same = TRUE;
3165
3166           SVN_ERR(svn_wc_get_default_ignores(&ignores, merge_b->ctx->config,
3167                                              scratch_pool));
3168
3169           /* None of the descendants was modified, but maybe there are
3170              descendants we haven't walked?
3171
3172              Note that we aren't interested in changes, as we already verified
3173              changes in the paths touched by the merge. And the existence of
3174              other paths is enough to mark the directory edited */
3175           err = svn_wc_walk_status(merge_b->ctx->wc_ctx, local_abspath,
3176                                    svn_depth_infinity, TRUE /* get-all */,
3177                                    FALSE /* no-ignore */,
3178                                    TRUE /* ignore-text-mods */, ignores,
3179                                    verify_touched_by_del_check, delb,
3180                                    merge_b->ctx->cancel_func,
3181                                    merge_b->ctx->cancel_baton,
3182                                    scratch_pool);
3183
3184           if (err)
3185             {
3186               if (err->apr_err != SVN_ERR_CEASE_INVOCATION)
3187                 return svn_error_trace(err);
3188
3189               svn_error_clear(err);
3190             }
3191
3192           same = ! delb->found_edit;
3193         }
3194     }
3195
3196   if (same && !merge_b->dry_run)
3197     {
3198       svn_error_t *err;
3199
3200       err = svn_wc_delete4(merge_b->ctx->wc_ctx, local_abspath,
3201                            FALSE /* keep_local */, FALSE /* unversioned */,
3202                            merge_b->ctx->cancel_func,
3203                            merge_b->ctx->cancel_baton,
3204                            NULL, NULL /* no notify */,
3205                            scratch_pool);
3206
3207       if (err)
3208         {
3209           if (err->apr_err != SVN_ERR_WC_LEFT_LOCAL_MOD)
3210             return svn_error_trace(err);
3211
3212           svn_error_clear(err);
3213           same = FALSE;
3214         }
3215     }
3216
3217   if (! same)
3218     {
3219       /* If the attempt to delete an existing directory failed,
3220        * the directory has local modifications (e.g. locally added
3221        * files, or property changes). Flag a tree conflict. */
3222
3223       /* This handles use case 5 described in the paper attached to issue
3224        * #2282.  See also notes/tree-conflicts/detection.txt
3225        */
3226       SVN_ERR(record_tree_conflict(merge_b, local_abspath, db->parent_baton,
3227                                    svn_node_dir,
3228                                    svn_wc_conflict_action_delete,
3229                                    svn_wc_conflict_reason_edited,
3230                                    NULL, TRUE,
3231                                    scratch_pool));
3232     }
3233   else
3234     {
3235       /* Record that we might have deleted mergeinfo */
3236       if (working_props
3237           && svn_hash_gets(working_props, SVN_PROP_MERGEINFO))
3238         {
3239           alloc_and_store_path(&merge_b->paths_with_deleted_mergeinfo,
3240                                local_abspath, merge_b->pool);
3241         }
3242
3243       SVN_ERR(record_update_delete(merge_b, db->parent_baton, local_abspath,
3244                                    svn_node_dir, scratch_pool));
3245     }
3246
3247   return SVN_NO_ERROR;
3248 }
3249
3250 /* An svn_diff_tree_processor_t function.
3251  *
3252  * Called after merge_dir_opened() when a node itself didn't change between
3253  * the left and right source.
3254  *
3255  * After the merge_dir_opened() but before the call to this merge_dir_closed()
3256  * function all descendants will have been processed.
3257  */
3258 static svn_error_t *
3259 merge_dir_closed(const char *relpath,
3260                  const svn_diff_source_t *left_source,
3261                  const svn_diff_source_t *right_source,
3262                  void *dir_baton,
3263                  const struct svn_diff_tree_processor_t *processor,
3264                  apr_pool_t *scratch_pool)
3265 {
3266   merge_cmd_baton_t *merge_b = processor->baton;
3267   struct merge_dir_baton_t *db = dir_baton;
3268
3269   SVN_ERR(handle_pending_notifications(merge_b, db, scratch_pool));
3270
3271   return SVN_NO_ERROR;
3272 }
3273
3274 /* An svn_diff_tree_processor_t function.
3275
3276    Called when the diff driver wants to report an absent path.
3277
3278    In case of merges this happens when the diff encounters a server-excluded
3279    path.
3280
3281    We register a skipped path, which will make parent mergeinfo non-
3282    inheritable. This ensures that a future merge might see these skipped
3283    changes as eligable for merging.
3284
3285    For legacy reasons we also notify the path as skipped.
3286  */
3287 static svn_error_t *
3288 merge_node_absent(const char *relpath,
3289                   void *dir_baton,
3290                   const svn_diff_tree_processor_t *processor,
3291                   apr_pool_t *scratch_pool)
3292 {
3293   merge_cmd_baton_t *merge_b = processor->baton;
3294   struct merge_dir_baton_t *db = dir_baton;
3295
3296   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
3297                                               relpath, scratch_pool);
3298
3299   SVN_ERR(record_skip(merge_b, local_abspath, svn_node_unknown,
3300                       svn_wc_notify_skip, svn_wc_notify_state_missing,
3301                       db, scratch_pool));
3302
3303   return SVN_NO_ERROR;
3304 }
3305
3306 /*-----------------------------------------------------------------------*/
3307 \f
3308 /*** Merge Notification ***/
3309
3310
3311 /* Finds a nearest ancestor in CHILDREN_WITH_MERGEINFO for LOCAL_ABSPATH. If
3312    PATH_IS_OWN_ANCESTOR is TRUE then a child in CHILDREN_WITH_MERGEINFO
3313    where child->abspath == PATH is considered PATH's ancestor.  If FALSE,
3314    then child->abspath must be a proper ancestor of PATH.
3315
3316    CHILDREN_WITH_MERGEINFO is expected to be sorted in Depth first
3317    order of path. */
3318 static svn_client__merge_path_t *
3319 find_nearest_ancestor(const apr_array_header_t *children_with_mergeinfo,
3320                       svn_boolean_t path_is_own_ancestor,
3321                       const char *local_abspath)
3322 {
3323   int i;
3324
3325   SVN_ERR_ASSERT_NO_RETURN(children_with_mergeinfo != NULL);
3326
3327   for (i = children_with_mergeinfo->nelts - 1; i >= 0 ; i--)
3328     {
3329       svn_client__merge_path_t *child =
3330         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
3331
3332       if (svn_dirent_is_ancestor(child->abspath, local_abspath)
3333           && (path_is_own_ancestor
3334               || strcmp(child->abspath, local_abspath) != 0))
3335         return child;
3336     }
3337   return NULL;
3338 }
3339
3340 /* Find the highest level path in a merge target (possibly the merge target
3341    itself) to use in a merge notification header.
3342
3343    Return the svn_client__merge_path_t * representing the most distant
3344    ancestor in CHILDREN_WITH_MERGEINFO of LOCAL_ABSPATH where said
3345    ancestor's first remaining ranges element (per the REMAINING_RANGES
3346    member of the ancestor) intersect with the first remaining ranges element
3347    for every intermediate ancestor svn_client__merge_path_t * of
3348    LOCAL_ABSPATH.  If no such ancestor is found return NULL.
3349
3350    If the remaining ranges of the elements in CHILDREN_WITH_MERGEINFO
3351    represent a forward merge, then set *START to the oldest revision found
3352    in any of the intersecting ancestors and *END to the youngest revision
3353    found.  If the remaining ranges of the elements in CHILDREN_WITH_MERGEINFO
3354    represent a reverse merge, then set *START to the youngest revision
3355    found and *END to the oldest revision found.  If no ancestors are found
3356    then set *START and *END to SVN_INVALID_REVNUM.
3357
3358    If PATH_IS_OWN_ANCESTOR is TRUE then a child in CHILDREN_WITH_MERGEINFO
3359    where child->abspath == PATH is considered PATH's ancestor.  If FALSE,
3360    then child->abspath must be a proper ancestor of PATH.
3361
3362    See the CHILDREN_WITH_MERGEINFO ARRAY global comment for more
3363    information. */
3364 static svn_client__merge_path_t *
3365 find_nearest_ancestor_with_intersecting_ranges(
3366   svn_revnum_t *start,
3367   svn_revnum_t *end,
3368   const apr_array_header_t *children_with_mergeinfo,
3369   svn_boolean_t path_is_own_ancestor,
3370   const char *local_abspath)
3371 {
3372   int i;
3373   svn_client__merge_path_t *nearest_ancestor = NULL;
3374
3375   *start = SVN_INVALID_REVNUM;
3376   *end = SVN_INVALID_REVNUM;
3377
3378   SVN_ERR_ASSERT_NO_RETURN(children_with_mergeinfo != NULL);
3379
3380   for (i = children_with_mergeinfo->nelts - 1; i >= 0 ; i--)
3381     {
3382       svn_client__merge_path_t *child =
3383         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
3384
3385       if (svn_dirent_is_ancestor(child->abspath, local_abspath)
3386           && (path_is_own_ancestor
3387               || strcmp(child->abspath, local_abspath) != 0))
3388         {
3389           if (nearest_ancestor == NULL)
3390             {
3391               /* Found an ancestor. */
3392               nearest_ancestor = child;
3393
3394               if (child->remaining_ranges)
3395                 {
3396                   svn_merge_range_t *r1 = APR_ARRAY_IDX(
3397                     child->remaining_ranges, 0, svn_merge_range_t *);
3398                   *start = r1->start;
3399                   *end = r1->end;
3400                 }
3401               else
3402                 {
3403                   /* If CHILD->REMAINING_RANGES is null then LOCAL_ABSPATH
3404                      is inside an absent subtree in the merge target. */
3405                   *start = SVN_INVALID_REVNUM;
3406                   *end = SVN_INVALID_REVNUM;
3407                   break;
3408                 }
3409             }
3410           else
3411             {
3412               /* We'e found another ancestor for LOCAL_ABSPATH.  Do its
3413                  first remaining range intersect with the previously
3414                  found ancestor? */
3415               svn_merge_range_t *r1 =
3416                 APR_ARRAY_IDX(nearest_ancestor->remaining_ranges, 0,
3417                               svn_merge_range_t *);
3418               svn_merge_range_t *r2 =
3419                 APR_ARRAY_IDX(child->remaining_ranges, 0,
3420                               svn_merge_range_t *);
3421
3422               if (r1 && r2)
3423                 {
3424                   svn_merge_range_t range1;
3425                   svn_merge_range_t range2;
3426                   svn_boolean_t reverse_merge = r1->start > r2->end;
3427
3428                   /* Flip endpoints if this is a reverse merge. */
3429                   if (reverse_merge)
3430                     {
3431                       range1.start = r1->end;
3432                       range1.end = r1->start;
3433                       range2.start = r2->end;
3434                       range2.end = r2->start;
3435                     }
3436                   else
3437                     {
3438                       range1.start = r1->start;
3439                       range1.end = r1->end;
3440                       range2.start = r2->start;
3441                       range2.end = r2->end;
3442                     }
3443
3444                   if (range1.start < range2.end && range2.start < range1.end)
3445                     {
3446                       *start = reverse_merge ?
3447                         MAX(r1->start, r2->start) : MIN(r1->start, r2->start);
3448                       *end = reverse_merge ?
3449                         MIN(r1->end, r2->end) : MAX(r1->end, r2->end);
3450                       nearest_ancestor = child;
3451                     }
3452                 }
3453             }
3454         }
3455     }
3456   return nearest_ancestor;
3457 }
3458
3459 /* Notify that we're starting to record mergeinfo for the merge of the
3460  * revision range RANGE into TARGET_ABSPATH.  RANGE should be null if the
3461  * merge sources are not from the same URL.
3462  *
3463  * This calls the client's notification receiver (as found in the client
3464  * context), with a WC abspath.
3465  */
3466 static void
3467 notify_mergeinfo_recording(const char *target_abspath,
3468                            const svn_merge_range_t *range,
3469                            svn_client_ctx_t *ctx,
3470                            apr_pool_t *pool)
3471 {
3472   if (ctx->notify_func2)
3473     {
3474       svn_wc_notify_t *n = svn_wc_create_notify(
3475         target_abspath, svn_wc_notify_merge_record_info_begin, pool);
3476
3477       n->merge_range = range ? svn_merge_range_dup(range, pool) : NULL;
3478       ctx->notify_func2(ctx->notify_baton2, n, pool);
3479     }
3480 }
3481
3482 /* Notify that we're completing the merge into TARGET_ABSPATH.
3483  *
3484  * This calls the client's notification receiver (as found in the client
3485  * context), with a WC abspath.
3486  */
3487 static void
3488 notify_merge_completed(const char *target_abspath,
3489                        svn_client_ctx_t *ctx,
3490                        apr_pool_t *pool)
3491 {
3492   if (ctx->notify_func2)
3493     {
3494       svn_wc_notify_t *n
3495         = svn_wc_create_notify(target_abspath, svn_wc_notify_merge_completed,
3496                                pool);
3497       ctx->notify_func2(ctx->notify_baton2, n, pool);
3498     }
3499 }
3500
3501 /* Is the notification the result of a real operative merge? */
3502 #define IS_OPERATIVE_NOTIFICATION(notify)  \
3503                     (notify->content_state == svn_wc_notify_state_conflicted \
3504                      || notify->content_state == svn_wc_notify_state_merged  \
3505                      || notify->content_state == svn_wc_notify_state_changed \
3506                      || notify->prop_state == svn_wc_notify_state_conflicted \
3507                      || notify->prop_state == svn_wc_notify_state_merged     \
3508                      || notify->prop_state == svn_wc_notify_state_changed    \
3509                      || notify->action == svn_wc_notify_update_add \
3510                      || notify->action == svn_wc_notify_tree_conflict)
3511
3512
3513 /* Remove merge source gaps from range used for merge notifications.
3514    See http://subversion.tigris.org/issues/show_bug.cgi?id=4138
3515
3516    If IMPLICIT_SRC_GAP is not NULL then it is a rangelist containing a
3517    single range (see the implicit_src_gap member of merge_cmd_baton_t).
3518    RANGE describes a (possibly reverse) merge.
3519
3520    If IMPLICIT_SRC_GAP is not NULL and it's sole range intersects with
3521    the older revision in *RANGE, then remove IMPLICIT_SRC_GAP's range
3522    from *RANGE. */
3523 static void
3524 remove_source_gap(svn_merge_range_t *range,
3525                   apr_array_header_t *implicit_src_gap)
3526 {
3527   if (implicit_src_gap)
3528     {
3529       svn_merge_range_t *gap_range =
3530         APR_ARRAY_IDX(implicit_src_gap, 0, svn_merge_range_t *);
3531       if (range->start < range->end)
3532         {
3533           if (gap_range->start == range->start)
3534             range->start = gap_range->end;
3535         }
3536       else /* Reverse merge */
3537         {
3538           if (gap_range->start == range->end)
3539             range->end = gap_range->end;
3540         }
3541     }
3542 }
3543
3544 /* Notify that we're starting a merge
3545  *
3546  * This calls the client's notification receiver (as found in the client
3547  * context), with a WC abspath.
3548  */
3549 static svn_error_t *
3550 notify_merge_begin(merge_cmd_baton_t *merge_b,
3551                    const char *local_abspath,
3552                    svn_boolean_t delete_action,
3553                    apr_pool_t *scratch_pool)
3554 {
3555   svn_wc_notify_t *notify;
3556   svn_merge_range_t n_range =
3557     {SVN_INVALID_REVNUM, SVN_INVALID_REVNUM, TRUE};
3558   const char *notify_abspath;
3559
3560   if (! merge_b->ctx->notify_func2)
3561     return SVN_NO_ERROR;
3562
3563   /* If our merge sources are ancestors of one another... */
3564   if (merge_b->merge_source.ancestral)
3565     {
3566       const svn_client__merge_path_t *child;
3567       /* Find NOTIFY->PATH's nearest ancestor in
3568          NOTIFY->CHILDREN_WITH_MERGEINFO.  Normally we consider a child in
3569          NOTIFY->CHILDREN_WITH_MERGEINFO representing PATH to be an
3570          ancestor of PATH, but if this is a deletion of PATH then the
3571          notification must be for a proper ancestor of PATH.  This ensures
3572          we don't get notifications like:
3573
3574            --- Merging rX into 'PARENT/CHILD'
3575            D    PARENT/CHILD
3576
3577          But rather:
3578
3579            --- Merging rX into 'PARENT'
3580            D    PARENT/CHILD
3581       */
3582
3583       child = find_nearest_ancestor_with_intersecting_ranges(
3584         &(n_range.start), &(n_range.end),
3585         merge_b->notify_begin.nodes_with_mergeinfo,
3586         ! delete_action, local_abspath);
3587
3588       if (!child && delete_action)
3589         {
3590           /* Triggered by file replace in single-file-merge */
3591           child = find_nearest_ancestor(merge_b->notify_begin.nodes_with_mergeinfo,
3592                                         TRUE, local_abspath);
3593         }
3594
3595       assert(child != NULL); /* Should always find the merge anchor */
3596
3597       if (! child)
3598         return SVN_NO_ERROR;
3599
3600       if (merge_b->notify_begin.last_abspath != NULL
3601           && strcmp(child->abspath, merge_b->notify_begin.last_abspath) == 0)
3602         {
3603           /* Don't notify the same merge again */
3604           return SVN_NO_ERROR;
3605         }
3606
3607       merge_b->notify_begin.last_abspath = child->abspath;
3608
3609       if (child->absent || child->remaining_ranges->nelts == 0
3610           || !SVN_IS_VALID_REVNUM(n_range.start))
3611         {
3612           /* No valid information for an header */
3613           return SVN_NO_ERROR;
3614         }
3615
3616       notify_abspath = child->abspath;
3617     }
3618   else
3619     {
3620       if (merge_b->notify_begin.last_abspath)
3621         return SVN_NO_ERROR; /* already notified */
3622
3623       notify_abspath = merge_b->target->abspath;
3624       /* Store something in last_abspath. Any value would do */
3625       merge_b->notify_begin.last_abspath = merge_b->target->abspath;
3626     }
3627
3628   notify = svn_wc_create_notify(notify_abspath,
3629                                 merge_b->same_repos
3630                                       ? svn_wc_notify_merge_begin
3631                                       : svn_wc_notify_foreign_merge_begin,
3632                                 scratch_pool);
3633
3634   if (SVN_IS_VALID_REVNUM(n_range.start))
3635     {
3636       /* If the merge source has a gap, then don't mention
3637          those gap revisions in the notification. */
3638       remove_source_gap(&n_range, merge_b->implicit_src_gap);
3639       notify->merge_range = &n_range;
3640     }
3641   else
3642     {
3643       notify->merge_range = NULL;
3644     }
3645
3646   (*merge_b->ctx->notify_func2)(merge_b->ctx->notify_baton2, notify,
3647                                 scratch_pool);
3648
3649   return SVN_NO_ERROR;
3650 }
3651
3652 /* Set *OUT_RANGELIST to the intersection of IN_RANGELIST with the simple
3653  * (inheritable) revision range REV1:REV2, according to CONSIDER_INHERITANCE.
3654  * If REV1 is equal to REV2, the result is an empty rangelist, otherwise
3655  * REV1 must be less than REV2.
3656  *
3657  * Note: If CONSIDER_INHERITANCE is FALSE, the effect is to treat any non-
3658  * inheritable input ranges as if they were inheritable.  If it is TRUE, the
3659  * effect is to discard any non-inheritable input ranges.  Therefore the
3660  * ranges in *OUT_RANGELIST will always be inheritable. */
3661 static svn_error_t *
3662 rangelist_intersect_range(svn_rangelist_t **out_rangelist,
3663                           const svn_rangelist_t *in_rangelist,
3664                           svn_revnum_t rev1,
3665                           svn_revnum_t rev2,
3666                           svn_boolean_t consider_inheritance,
3667                           apr_pool_t *result_pool,
3668                           apr_pool_t *scratch_pool)
3669 {
3670   SVN_ERR_ASSERT(rev1 <= rev2);
3671
3672   if (rev1 < rev2)
3673     {
3674       svn_rangelist_t *simple_rangelist =
3675         svn_rangelist__initialize(rev1, rev2, TRUE, scratch_pool);
3676
3677       SVN_ERR(svn_rangelist_intersect(out_rangelist,
3678                                       simple_rangelist, in_rangelist,
3679                                       consider_inheritance, result_pool));
3680     }
3681   else
3682     {
3683       *out_rangelist = apr_array_make(result_pool, 0,
3684                                       sizeof(svn_merge_range_t *));
3685     }
3686   return SVN_NO_ERROR;
3687 }
3688
3689 /* Helper for fix_deleted_subtree_ranges().  Like fix_deleted_subtree_ranges()
3690    this function should only be called when honoring mergeinfo.
3691
3692    CHILD, PARENT, REVISION1, REVISION2, and RA_SESSION are all cascaded from
3693    fix_deleted_subtree_ranges() -- see that function for more information on
3694    each.
3695
3696    If PARENT is not the merge target then PARENT must have already have been
3697    processed by this function as a child.  Specifically, this means that
3698    PARENT->REMAINING_RANGES must already be populated -- it can be an empty
3699    rangelist but cannot be NULL.
3700
3701    PRIMARY_URL is the merge source url of CHILD at the younger of REVISION1
3702    and REVISION2.
3703
3704    Since this function is only invoked for subtrees of the merge target, the
3705    guarantees afforded by normalize_merge_sources() don't apply - see the
3706    'MERGEINFO MERGE SOURCE NORMALIZATION' comment at the top of this file.
3707    Therefore it is possible that PRIMARY_URL@REVISION1 and
3708    PRIMARY_URL@REVISION2 don't describe the endpoints of an unbroken line of
3709    history.  The purpose of this helper is to identify these cases of broken
3710    history and adjust CHILD->REMAINING_RANGES in such a way we don't later try
3711    to describe nonexistent path/revisions to the merge report editor -- see
3712    drive_merge_report_editor().
3713
3714    If PRIMARY_URL@REVISION1 and PRIMARY_URL@REVISION2 describe an unbroken
3715    line of history then do nothing and leave CHILD->REMAINING_RANGES as-is.
3716
3717    If neither PRIMARY_URL@REVISION1 nor PRIMARY_URL@REVISION2 exist then
3718    there is nothing to merge to CHILD->ABSPATH so set CHILD->REMAINING_RANGES
3719    equal to PARENT->REMAINING_RANGES.  This will cause the subtree to
3720    effectively ignore CHILD -- see 'Note: If the first svn_merge_range_t...'
3721    in drive_merge_report_editor()'s doc string.
3722
3723    If PRIMARY_URL@REVISION1 *xor* PRIMARY_URL@REVISION2 exist then we take the
3724    subset of REVISION1:REVISION2 in CHILD->REMAINING_RANGES at which
3725    PRIMARY_URL doesn't exist and set that subset equal to
3726    PARENT->REMAINING_RANGES' intersection with that non-existent range.  Why?
3727    Because this causes CHILD->REMAINING_RANGES to be identical to
3728    PARENT->REMAINING_RANGES for revisions between REVISION1 and REVISION2 at
3729    which PRIMARY_URL doesn't exist.  As mentioned above this means that
3730    drive_merge_report_editor() won't attempt to describe these non-existent
3731    subtree path/ranges to the reporter (which would break the merge).
3732
3733    If the preceding paragraph wasn't terribly clear then what follows spells
3734    out this function's behavior a bit more explicitly:
3735
3736    For forward merges (REVISION1 < REVISION2)
3737
3738      If PRIMARY_URL@REVISION1 exists but PRIMARY_URL@REVISION2 doesn't, then
3739      find the revision 'N' in which PRIMARY_URL@REVISION1 was deleted.  Leave
3740      the subset of CHILD->REMAINING_RANGES that intersects with
3741      REVISION1:(N - 1) as-is and set the subset of CHILD->REMAINING_RANGES
3742      that intersects with (N - 1):REVISION2 equal to PARENT->REMAINING_RANGES'
3743      intersection with (N - 1):REVISION2.
3744
3745      If PRIMARY_URL@REVISION1 doesn't exist but PRIMARY_URL@REVISION2 does,
3746      then find the revision 'M' in which PRIMARY_URL@REVISION2 came into
3747      existence.  Leave the subset of CHILD->REMAINING_RANGES that intersects with
3748      (M - 1):REVISION2 as-is and set the subset of CHILD->REMAINING_RANGES
3749      that intersects with REVISION1:(M - 1) equal to PARENT->REMAINING_RANGES'
3750      intersection with REVISION1:(M - 1).
3751
3752    For reverse merges (REVISION1 > REVISION2)
3753
3754      If PRIMARY_URL@REVISION1 exists but PRIMARY_URL@REVISION2 doesn't, then
3755      find the revision 'N' in which PRIMARY_URL@REVISION1 came into existence.
3756      Leave the subset of CHILD->REMAINING_RANGES that intersects with
3757      REVISION2:(N - 1) as-is and set the subset of CHILD->REMAINING_RANGES
3758      that intersects with (N - 1):REVISION1 equal to PARENT->REMAINING_RANGES'
3759      intersection with (N - 1):REVISION1.
3760
3761      If PRIMARY_URL@REVISION1 doesn't exist but PRIMARY_URL@REVISION2 does,
3762      then find the revision 'M' in which PRIMARY_URL@REVISION2 came into
3763      existence.  Leave the subset of CHILD->REMAINING_RANGES that intersects with
3764      REVISION2:(M - 1) as-is and set the subset of CHILD->REMAINING_RANGES
3765      that intersects with (M - 1):REVISION1 equal to PARENT->REMAINING_RANGES'
3766      intersection with REVISION1:(M - 1).
3767
3768    SCRATCH_POOL is used for all temporary allocations.  Changes to CHILD are
3769    allocated in RESULT_POOL. */
3770 static svn_error_t *
3771 adjust_deleted_subtree_ranges(svn_client__merge_path_t *child,
3772                               svn_client__merge_path_t *parent,
3773                               svn_revnum_t revision1,
3774                               svn_revnum_t revision2,
3775                               const char *primary_url,
3776                               svn_ra_session_t *ra_session,
3777                               svn_client_ctx_t *ctx,
3778                               apr_pool_t *result_pool,
3779                               apr_pool_t *scratch_pool)
3780 {
3781   svn_boolean_t is_rollback = revision2 < revision1;
3782   svn_revnum_t younger_rev = is_rollback ? revision1 : revision2;
3783   svn_revnum_t peg_rev = younger_rev;
3784   svn_revnum_t older_rev = is_rollback ? revision2 : revision1;
3785   apr_array_header_t *segments;
3786   svn_error_t *err;
3787
3788   SVN_ERR_ASSERT(parent->remaining_ranges);
3789
3790   err = svn_client__repos_location_segments(&segments, ra_session,
3791                                             primary_url, peg_rev,
3792                                             younger_rev, older_rev, ctx,
3793                                             scratch_pool);
3794
3795   /* If PRIMARY_URL@peg_rev doesn't exist then
3796       svn_client__repos_location_segments() typically returns an
3797       SVN_ERR_FS_NOT_FOUND error, but if it doesn't exist for a
3798       forward merge over ra_neon then we get SVN_ERR_RA_DAV_REQUEST_FAILED.
3799       http://subversion.tigris.org/issues/show_bug.cgi?id=3137 fixed some of
3800       the cases where different RA layers returned different error codes to
3801       signal the "path not found"...but it looks like there is more to do.
3802
3803       ### Do we still need to special case for ra_neon (since it no longer
3804           exists)? */
3805   if (err)
3806     {
3807       if (err->apr_err == SVN_ERR_FS_NOT_FOUND
3808           || err->apr_err == SVN_ERR_RA_DAV_REQUEST_FAILED)
3809         {
3810           /* PRIMARY_URL@peg_rev doesn't exist.  Check if PRIMARY_URL@older_rev
3811              exists, if neither exist then the editor can simply ignore this
3812              subtree. */
3813           const char *rel_source_path;  /* PRIMARY_URL relative to RA_SESSION */
3814           svn_node_kind_t kind;
3815
3816           svn_error_clear(err);
3817           err = NULL;
3818
3819           SVN_ERR(svn_ra_get_path_relative_to_session(
3820                     ra_session, &rel_source_path, primary_url, scratch_pool));
3821
3822           SVN_ERR(svn_ra_check_path(ra_session, rel_source_path,
3823                                     older_rev, &kind, scratch_pool));
3824           if (kind == svn_node_none)
3825             {
3826               /* Neither PRIMARY_URL@peg_rev nor PRIMARY_URL@older_rev exist,
3827                  so there is nothing to merge.  Set CHILD->REMAINING_RANGES
3828                  identical to PARENT's. */
3829               child->remaining_ranges =
3830                 svn_rangelist_dup(parent->remaining_ranges, scratch_pool);
3831             }
3832           else
3833             {
3834               svn_rangelist_t *deleted_rangelist;
3835               svn_revnum_t rev_primary_url_deleted;
3836
3837               /* PRIMARY_URL@older_rev exists, so it was deleted at some
3838                  revision prior to peg_rev, find that revision. */
3839               SVN_ERR(svn_ra_get_deleted_rev(ra_session, rel_source_path,
3840                                              older_rev, younger_rev,
3841                                              &rev_primary_url_deleted,
3842                                              scratch_pool));
3843
3844               /* PRIMARY_URL@older_rev exists and PRIMARY_URL@peg_rev doesn't,
3845                  so svn_ra_get_deleted_rev() should always find the revision
3846                  PRIMARY_URL@older_rev was deleted. */
3847               SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(rev_primary_url_deleted));
3848
3849               /* If this is a reverse merge reorder CHILD->REMAINING_RANGES and
3850                  PARENT->REMAINING_RANGES so both will work with the
3851                  svn_rangelist_* APIs below. */
3852               if (is_rollback)
3853                 {
3854                   /* svn_rangelist_reverse operates in place so it's safe
3855                      to use our scratch_pool. */
3856                   SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
3857                                                 scratch_pool));
3858                   SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
3859                                                 scratch_pool));
3860                 }
3861
3862               /* Find the intersection of CHILD->REMAINING_RANGES with the
3863                  range over which PRIMARY_URL@older_rev exists (ending at
3864                  the youngest revision at which it still exists). */
3865               SVN_ERR(rangelist_intersect_range(&child->remaining_ranges,
3866                                                 child->remaining_ranges,
3867                                                 older_rev,
3868                                                 rev_primary_url_deleted - 1,
3869                                                 FALSE,
3870                                                 scratch_pool, scratch_pool));
3871
3872               /* Merge into CHILD->REMAINING_RANGES the intersection of
3873                  PARENT->REMAINING_RANGES with the range beginning when
3874                  PRIMARY_URL@older_rev was deleted until younger_rev. */
3875               SVN_ERR(rangelist_intersect_range(&deleted_rangelist,
3876                                                 parent->remaining_ranges,
3877                                                 rev_primary_url_deleted - 1,
3878                                                 peg_rev,
3879                                                 FALSE,
3880                                                 scratch_pool, scratch_pool));
3881               SVN_ERR(svn_rangelist_merge2(child->remaining_ranges,
3882                                            deleted_rangelist, scratch_pool,
3883                                            scratch_pool));
3884
3885               /* Return CHILD->REMAINING_RANGES and PARENT->REMAINING_RANGES
3886                  to reverse order if necessary. */
3887               if (is_rollback)
3888                 {
3889                   SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
3890                                                 scratch_pool));
3891                   SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
3892                                                 scratch_pool));
3893                 }
3894             }
3895         }
3896       else
3897         {
3898           return svn_error_trace(err);
3899         }
3900     }
3901   else /* PRIMARY_URL@peg_rev exists. */
3902     {
3903       svn_rangelist_t *non_existent_rangelist;
3904       svn_location_segment_t *segment =
3905         APR_ARRAY_IDX(segments, (segments->nelts - 1),
3906                       svn_location_segment_t *);
3907
3908       /* We know PRIMARY_URL@peg_rev exists as the call to
3909          svn_client__repos_location_segments() succeeded.  If there is only
3910          one segment that starts at oldest_rev then we know that
3911          PRIMARY_URL@oldest_rev:PRIMARY_URL@peg_rev describes an unbroken
3912          line of history, so there is nothing more to adjust in
3913          CHILD->REMAINING_RANGES. */
3914       if (segment->range_start == older_rev)
3915         {
3916           return SVN_NO_ERROR;
3917         }
3918
3919       /* If this is a reverse merge reorder CHILD->REMAINING_RANGES and
3920          PARENT->REMAINING_RANGES so both will work with the
3921          svn_rangelist_* APIs below. */
3922       if (is_rollback)
3923         {
3924           SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
3925                                         scratch_pool));
3926           SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
3927                                         scratch_pool));
3928         }
3929
3930       /* Intersect CHILD->REMAINING_RANGES with the range where PRIMARY_URL
3931          exists.  Since segment doesn't span older_rev:peg_rev we know
3932          PRIMARY_URL@peg_rev didn't come into existence until
3933          segment->range_start + 1. */
3934       SVN_ERR(rangelist_intersect_range(&child->remaining_ranges,
3935                                         child->remaining_ranges,
3936                                         segment->range_start, peg_rev,
3937                                         FALSE, scratch_pool, scratch_pool));
3938
3939       /* Merge into CHILD->REMAINING_RANGES the intersection of
3940          PARENT->REMAINING_RANGES with the range before PRIMARY_URL@peg_rev
3941          came into existence. */
3942       SVN_ERR(rangelist_intersect_range(&non_existent_rangelist,
3943                                         parent->remaining_ranges,
3944                                         older_rev, segment->range_start,
3945                                         FALSE, scratch_pool, scratch_pool));
3946       SVN_ERR(svn_rangelist_merge2(child->remaining_ranges,
3947                                    non_existent_rangelist, scratch_pool,
3948                                    scratch_pool));
3949
3950       /* Return CHILD->REMAINING_RANGES and PARENT->REMAINING_RANGES
3951          to reverse order if necessary. */
3952       if (is_rollback)
3953         {
3954           SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
3955                                         scratch_pool));
3956           SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
3957                                         scratch_pool));
3958         }
3959     }
3960
3961   /* Make a lasting copy of CHILD->REMAINING_RANGES using POOL. */
3962   child->remaining_ranges = svn_rangelist_dup(child->remaining_ranges,
3963                                               result_pool);
3964   return SVN_NO_ERROR;
3965 }
3966
3967 /* Helper for do_directory_merge().
3968
3969    SOURCE is cascaded from the argument of the same name in
3970    do_directory_merge().  TARGET is the merge target.  RA_SESSION is the
3971    session for the younger of SOURCE->loc1 and SOURCE->loc2.
3972
3973    Adjust the subtrees in CHILDREN_WITH_MERGEINFO so that we don't
3974    later try to describe invalid paths in drive_merge_report_editor().
3975    This function is just a thin wrapper around
3976    adjust_deleted_subtree_ranges(), which see for further details.
3977
3978    SCRATCH_POOL is used for all temporary allocations.  Changes to
3979    CHILDREN_WITH_MERGEINFO are allocated in RESULT_POOL.
3980 */
3981 static svn_error_t *
3982 fix_deleted_subtree_ranges(const merge_source_t *source,
3983                            const merge_target_t *target,
3984                            svn_ra_session_t *ra_session,
3985                            apr_array_header_t *children_with_mergeinfo,
3986                            svn_client_ctx_t *ctx,
3987                            apr_pool_t *result_pool,
3988                            apr_pool_t *scratch_pool)
3989 {
3990   int i;
3991   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
3992   svn_boolean_t is_rollback = source->loc2->rev < source->loc1->rev;
3993
3994   assert(session_url_is(ra_session,
3995                         (is_rollback ? source->loc1 : source->loc2)->url,
3996                         scratch_pool));
3997
3998   /* CHILDREN_WITH_MERGEINFO is sorted in depth-first order, so
3999      start at index 1 to examine only subtrees. */
4000   for (i = 1; i < children_with_mergeinfo->nelts; i++)
4001     {
4002       svn_client__merge_path_t *child =
4003         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
4004       svn_client__merge_path_t *parent;
4005       svn_rangelist_t *deleted_rangelist, *added_rangelist;
4006
4007       SVN_ERR_ASSERT(child);
4008       if (child->absent)
4009         continue;
4010
4011       svn_pool_clear(iterpool);
4012
4013       /* Find CHILD's parent. */
4014       parent = find_nearest_ancestor(children_with_mergeinfo,
4015                                      FALSE, child->abspath);
4016
4017       /* Since CHILD is a subtree then its parent must be in
4018          CHILDREN_WITH_MERGEINFO, see the global comment
4019          'THE CHILDREN_WITH_MERGEINFO ARRAY'. */
4020       SVN_ERR_ASSERT(parent);
4021
4022       /* If this is a reverse merge reorder CHILD->REMAINING_RANGES
4023          so it will work with the svn_rangelist_diff API. */
4024       if (is_rollback)
4025         {
4026           SVN_ERR(svn_rangelist_reverse(child->remaining_ranges, iterpool));
4027           SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges, iterpool));
4028         }
4029
4030       SVN_ERR(svn_rangelist_diff(&deleted_rangelist, &added_rangelist,
4031                                  child->remaining_ranges,
4032                                  parent->remaining_ranges,
4033                                  TRUE, iterpool));
4034
4035       if (is_rollback)
4036         {
4037           SVN_ERR(svn_rangelist_reverse(child->remaining_ranges, iterpool));
4038           SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges, iterpool));
4039         }
4040
4041       /* If CHILD is the merge target we then know that SOURCE is provided
4042          by normalize_merge_sources() -- see 'MERGEINFO MERGE SOURCE
4043          NORMALIZATION'.  Due to this normalization we know that SOURCE
4044          describes an unbroken line of history such that the entire range
4045          described by SOURCE can potentially be merged to CHILD.
4046
4047          But if CHILD is a subtree we don't have the same guarantees about
4048          SOURCE as we do for the merge target.  SOURCE->loc1 and/or
4049          SOURCE->loc2 might not exist.
4050
4051          If one or both doesn't exist, then adjust CHILD->REMAINING_RANGES
4052          such that we don't later try to describe invalid subtrees in
4053          drive_merge_report_editor(), as that will break the merge.
4054          If CHILD has the same remaining ranges as PARENT however, then
4055          there is no need to make these adjustments, since
4056          drive_merge_report_editor() won't attempt to describe CHILD in this
4057          case, see the 'Note' in drive_merge_report_editor's docstring. */
4058       if (deleted_rangelist->nelts || added_rangelist->nelts)
4059         {
4060           const char *child_primary_source_url;
4061           const char *child_repos_src_path =
4062             svn_dirent_is_child(target->abspath, child->abspath, iterpool);
4063
4064           /* This loop is only processing subtrees, so CHILD->ABSPATH
4065              better be a proper child of the merge target. */
4066           SVN_ERR_ASSERT(child_repos_src_path);
4067
4068           child_primary_source_url =
4069             svn_path_url_add_component2((source->loc1->rev < source->loc2->rev)
4070                                         ? source->loc2->url : source->loc1->url,
4071                                         child_repos_src_path, iterpool);
4072
4073           SVN_ERR(adjust_deleted_subtree_ranges(child, parent,
4074                                                 source->loc1->rev,
4075                                                 source->loc2->rev,
4076                                                 child_primary_source_url,
4077                                                 ra_session,
4078                                                 ctx, result_pool, iterpool));
4079         }
4080     }
4081
4082   svn_pool_destroy(iterpool);
4083   return SVN_NO_ERROR;
4084 }
4085
4086 /*-----------------------------------------------------------------------*/
4087 \f
4088 /*** Determining What Remains To Be Merged ***/
4089
4090 /* Get explicit and/or implicit mergeinfo for the working copy path
4091    TARGET_ABSPATH.
4092
4093    If RECORDED_MERGEINFO is not NULL then set *RECORDED_MERGEINFO
4094    to TARGET_ABSPATH's explicit or inherited mergeinfo as dictated by
4095    INHERIT.
4096
4097    If IMPLICIT_MERGEINFO is not NULL then set *IMPLICIT_MERGEINFO
4098    to TARGET_ABSPATH's implicit mergeinfo (a.k.a. natural history).
4099
4100    If both RECORDED_MERGEINFO and IMPLICIT_MERGEINFO are not NULL and
4101    *RECORDED_MERGEINFO is inherited, then *IMPLICIT_MERGEINFO will be
4102    removed from *RECORDED_MERGEINFO.
4103
4104    If INHERITED is not NULL set *INHERITED to TRUE if *RECORDED_MERGEINFO
4105    is inherited rather than explicit.  If RECORDED_MERGEINFO is NULL then
4106    INHERITED is ignored.
4107
4108
4109    If IMPLICIT_MERGEINFO is not NULL then START and END are limits on
4110    the natural history sought, must both be valid revision numbers, and
4111    START must be greater than END.  If TARGET_ABSPATH's base revision
4112    is older than START, then the base revision is used as the younger
4113    bound in place of START.
4114
4115    RA_SESSION is an RA session open to the repository in which TARGET_ABSPATH
4116    lives.  It may be temporarily reparented as needed by this function.
4117
4118    Allocate *RECORDED_MERGEINFO and *IMPLICIT_MERGEINFO in RESULT_POOL.
4119    Use SCRATCH_POOL for any temporary allocations. */
4120 static svn_error_t *
4121 get_full_mergeinfo(svn_mergeinfo_t *recorded_mergeinfo,
4122                    svn_mergeinfo_t *implicit_mergeinfo,
4123                    svn_boolean_t *inherited,
4124                    svn_mergeinfo_inheritance_t inherit,
4125                    svn_ra_session_t *ra_session,
4126                    const char *target_abspath,
4127                    svn_revnum_t start,
4128                    svn_revnum_t end,
4129                    svn_client_ctx_t *ctx,
4130                    apr_pool_t *result_pool,
4131                    apr_pool_t *scratch_pool)
4132 {
4133   /* First, we get the real mergeinfo. */
4134   if (recorded_mergeinfo)
4135     {
4136       SVN_ERR(svn_client__get_wc_or_repos_mergeinfo(recorded_mergeinfo,
4137                                                     inherited,
4138                                                     NULL /* from_repos */,
4139                                                     FALSE,
4140                                                     inherit, ra_session,
4141                                                     target_abspath,
4142                                                     ctx, result_pool));
4143     }
4144
4145   if (implicit_mergeinfo)
4146     {
4147       svn_client__pathrev_t *target;
4148
4149       /* Assert that we have sane input. */
4150       SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(start) && SVN_IS_VALID_REVNUM(end)
4151                      && (start > end));
4152
4153       /* Retrieve the origin (original_*) of the node, or just the
4154          url if the node was not copied. */
4155       SVN_ERR(svn_client__wc_node_get_origin(&target, target_abspath, ctx,
4156                                              scratch_pool, scratch_pool));
4157
4158       if (! target)
4159         {
4160           /* We've been asked to operate on a locally added target, so its
4161            * implicit mergeinfo is empty. */
4162           *implicit_mergeinfo = apr_hash_make(result_pool);
4163         }
4164       else if (target->rev <= end)
4165         {
4166           /* We're asking about a range outside our natural history
4167              altogether.  That means our implicit mergeinfo is empty. */
4168           *implicit_mergeinfo = apr_hash_make(result_pool);
4169         }
4170       else
4171         {
4172           /* Fetch so-called "implicit mergeinfo" (that is, natural
4173              history). */
4174
4175           /* Do not ask for implicit mergeinfo from TARGET_ABSPATH's future.
4176              TARGET_ABSPATH might not even exist, and even if it does the
4177              working copy is *at* TARGET_REV so its implicit history ends
4178              at TARGET_REV! */
4179           if (target->rev < start)
4180             start = target->rev;
4181
4182           /* Fetch the implicit mergeinfo. */
4183           SVN_ERR(svn_client__get_history_as_mergeinfo(implicit_mergeinfo,
4184                                                        NULL,
4185                                                        target, start, end,
4186                                                        ra_session, ctx,
4187                                                        result_pool));
4188         }
4189     } /*if (implicit_mergeinfo) */
4190
4191   return SVN_NO_ERROR;
4192 }
4193
4194 /* Helper for ensure_implicit_mergeinfo().
4195
4196    PARENT, CHILD, REVISION1, REVISION2 and CTX
4197    are all cascaded from the arguments of the same names in
4198    ensure_implicit_mergeinfo().  PARENT and CHILD must both exist, i.e.
4199    this function should never be called where CHILD is the merge target.
4200
4201    If PARENT->IMPLICIT_MERGEINFO is NULL, obtain it from the server.
4202
4203    Set CHILD->IMPLICIT_MERGEINFO to the mergeinfo inherited from
4204    PARENT->IMPLICIT_MERGEINFO.  CHILD->IMPLICIT_MERGEINFO is allocated
4205    in RESULT_POOL.
4206
4207    RA_SESSION is an RA session open to the repository that contains CHILD.
4208    It may be temporarily reparented by this function.
4209    */
4210 static svn_error_t *
4211 inherit_implicit_mergeinfo_from_parent(svn_client__merge_path_t *parent,
4212                                        svn_client__merge_path_t *child,
4213                                        svn_revnum_t revision1,
4214                                        svn_revnum_t revision2,
4215                                        svn_ra_session_t *ra_session,
4216                                        svn_client_ctx_t *ctx,
4217                                        apr_pool_t *result_pool,
4218                                        apr_pool_t *scratch_pool)
4219 {
4220   const char *path_diff;
4221
4222   /* This only works on subtrees! */
4223   SVN_ERR_ASSERT(parent);
4224   SVN_ERR_ASSERT(child);
4225
4226   /* While PARENT must exist, it is possible we've deferred
4227      getting its implicit mergeinfo.  If so get it now. */
4228   if (!parent->implicit_mergeinfo)
4229     SVN_ERR(get_full_mergeinfo(NULL, &(parent->implicit_mergeinfo),
4230                                NULL, svn_mergeinfo_inherited,
4231                                ra_session, child->abspath,
4232                                MAX(revision1, revision2),
4233                                MIN(revision1, revision2),
4234                                ctx, result_pool, scratch_pool));
4235
4236   /* Let CHILD inherit PARENT's implicit mergeinfo. */
4237
4238   path_diff = svn_dirent_is_child(parent->abspath, child->abspath,
4239                                   scratch_pool);
4240   /* PARENT->PATH better be an ancestor of CHILD->ABSPATH! */
4241   SVN_ERR_ASSERT(path_diff);
4242
4243   SVN_ERR(svn_mergeinfo__add_suffix_to_mergeinfo(
4244             &child->implicit_mergeinfo, parent->implicit_mergeinfo,
4245             path_diff, result_pool, scratch_pool));
4246   child->implicit_mergeinfo = svn_mergeinfo_dup(child->implicit_mergeinfo,
4247                                                 result_pool);
4248   return SVN_NO_ERROR;
4249 }
4250
4251 /* Helper of filter_merged_revisions().
4252
4253    If we have deferred obtaining CHILD->IMPLICIT_MERGEINFO, then get
4254    it now, allocating it in RESULT_POOL.  If CHILD_INHERITS_PARENT is true
4255    then set CHILD->IMPLICIT_MERGEINFO to the mergeinfo inherited from
4256    PARENT->IMPLICIT_MERGEINFO, otherwise contact the repository.  Use
4257    SCRATCH_POOL for all temporary allocations.
4258
4259    RA_SESSION is an RA session open to the repository that contains CHILD.
4260    It may be temporarily reparented by this function.
4261
4262    PARENT, CHILD, REVISION1, REVISION2 and
4263    CTX are all cascaded from the arguments of the same name in
4264    filter_merged_revisions() and the same conditions for that function
4265    hold here. */
4266 static svn_error_t *
4267 ensure_implicit_mergeinfo(svn_client__merge_path_t *parent,
4268                           svn_client__merge_path_t *child,
4269                           svn_boolean_t child_inherits_parent,
4270                           svn_revnum_t revision1,
4271                           svn_revnum_t revision2,
4272                           svn_ra_session_t *ra_session,
4273                           svn_client_ctx_t *ctx,
4274                           apr_pool_t *result_pool,
4275                           apr_pool_t *scratch_pool)
4276 {
4277   /* If we haven't already found CHILD->IMPLICIT_MERGEINFO then
4278      contact the server to get it. */
4279
4280   if (child->implicit_mergeinfo)
4281     return SVN_NO_ERROR;
4282
4283   if (child_inherits_parent)
4284     SVN_ERR(inherit_implicit_mergeinfo_from_parent(parent,
4285                                                    child,
4286                                                    revision1,
4287                                                    revision2,
4288                                                    ra_session,
4289                                                    ctx,
4290                                                    result_pool,
4291                                                    scratch_pool));
4292   else
4293     SVN_ERR(get_full_mergeinfo(NULL,
4294                                &(child->implicit_mergeinfo),
4295                                NULL, svn_mergeinfo_inherited,
4296                                ra_session, child->abspath,
4297                                MAX(revision1, revision2),
4298                                MIN(revision1, revision2),
4299                                ctx, result_pool, scratch_pool));
4300
4301   return SVN_NO_ERROR;
4302 }
4303
4304 /* Helper for calculate_remaining_ranges().
4305
4306    Initialize CHILD->REMAINING_RANGES to a rangelist representing the
4307    requested merge of REVISION1:REVISION2 from MERGEINFO_PATH to
4308    CHILD->ABSPATH.
4309
4310    For forward merges remove any ranges from CHILD->REMAINING_RANGES that
4311    have already been merged to CHILD->ABSPATH per TARGET_MERGEINFO or
4312    CHILD->IMPLICIT_MERGEINFO.  For reverse merges remove any ranges from
4313    CHILD->REMAINING_RANGES that have not already been merged to CHILD->ABSPATH
4314    per TARGET_MERGEINFO or CHILD->IMPLICIT_MERGEINFO.  If we have deferred
4315    obtaining CHILD->IMPLICIT_MERGEINFO and it is necessary to use it for
4316    these calculations, then get it from the server, allocating it in
4317    RESULT_POOL.
4318
4319    CHILD represents a working copy path which is the merge target or one of
4320    the target's subtrees.  If not NULL, PARENT is CHILD's nearest path-wise
4321    ancestor - see 'THE CHILDREN_WITH_MERGEINFO ARRAY'.
4322
4323    If the function needs to consider CHILD->IMPLICIT_MERGEINFO and
4324    CHILD_INHERITS_IMPLICIT is true, then set CHILD->IMPLICIT_MERGEINFO to the
4325    mergeinfo inherited from PARENT->IMPLICIT_MERGEINFO.  Otherwise contact
4326    the repository for CHILD->IMPLICIT_MERGEINFO.
4327
4328    NOTE: If PARENT is present then this function must have previously been
4329    called for PARENT, i.e. if populate_remaining_ranges() is calling this
4330    function for a set of svn_client__merge_path_t* the calls must be made
4331    in depth-first order.
4332
4333    MERGEINFO_PATH is the merge source relative to the repository root.
4334
4335    REVISION1 and REVISION2 describe the merge range requested from
4336    MERGEINFO_PATH.
4337
4338    TARGET_RANGELIST is the portion of CHILD->ABSPATH's explicit or inherited
4339    mergeinfo that intersects with the merge history described by
4340    MERGEINFO_PATH@REVISION1:MERGEINFO_PATH@REVISION2.  TARGET_RANGELIST
4341    should be NULL if there is no explicit or inherited mergeinfo on
4342    CHILD->ABSPATH or an empty list if CHILD->ABSPATH has empty mergeinfo or
4343    explicit mergeinfo that exclusively describes non-intersecting history
4344    with MERGEINFO_PATH@REVISION1:MERGEINFO_PATH@REVISION2.
4345
4346    SCRATCH_POOL is used for all temporary allocations.
4347
4348    NOTE: This should only be called when honoring mergeinfo.
4349
4350    NOTE: Like calculate_remaining_ranges() if PARENT is present then this
4351    function must have previously been called for PARENT.
4352 */
4353 static svn_error_t *
4354 filter_merged_revisions(svn_client__merge_path_t *parent,
4355                         svn_client__merge_path_t *child,
4356                         const char *mergeinfo_path,
4357                         svn_rangelist_t *target_rangelist,
4358                         svn_revnum_t revision1,
4359                         svn_revnum_t revision2,
4360                         svn_boolean_t child_inherits_implicit,
4361                         svn_ra_session_t *ra_session,
4362                         svn_client_ctx_t *ctx,
4363                         apr_pool_t *result_pool,
4364                         apr_pool_t *scratch_pool)
4365 {
4366   svn_rangelist_t *requested_rangelist,
4367     *target_implicit_rangelist, *explicit_rangelist;
4368
4369   /* Convert REVISION1 and REVISION2 to a rangelist.
4370
4371      Note: Talking about a requested merge range's inheritability
4372      doesn't make much sense, but as we are using svn_merge_range_t
4373      to describe it we need to pick *something*.  Since all the
4374      rangelist manipulations in this function either don't consider
4375      inheritance by default or we are requesting that they don't (i.e.
4376      svn_rangelist_remove and svn_rangelist_intersect) then we could
4377      set the inheritability as FALSE, it won't matter either way. */
4378   requested_rangelist = svn_rangelist__initialize(revision1, revision2,
4379                                                   TRUE, scratch_pool);
4380
4381   /* Now filter out revisions that have already been merged to CHILD. */
4382
4383   if (revision1 > revision2) /* This is a reverse merge. */
4384     {
4385       svn_rangelist_t *added_rangelist, *deleted_rangelist;
4386
4387       /* The revert range and will need to be reversed for
4388          our svn_rangelist_* APIs to work properly. */
4389       SVN_ERR(svn_rangelist_reverse(requested_rangelist, scratch_pool));
4390
4391       /* Set EXPLICIT_RANGELIST to the list of source-range revs that are
4392          already recorded as merged to target. */
4393       if (target_rangelist)
4394         {
4395           /* Return the intersection of the revs which are both already
4396              represented by CHILD's explicit or inherited mergeinfo.
4397
4398              We don't consider inheritance when determining intersecting
4399              ranges.  If we *did* consider inheritance, then our calculation
4400              would be wrong.  For example, if the CHILD->REMAINING_RANGES is
4401              5:3 and TARGET_RANGELIST is r5* (non-inheritable) then the
4402              intersection would be r4.  And that would be wrong as we clearly
4403              want to reverse merge both r4 and r5 in this case.  Ignoring the
4404              ranges' inheritance results in an intersection of r4-5.
4405
4406              You might be wondering about CHILD's children, doesn't the above
4407              imply that we will reverse merge r4-5 from them?  Nope, this is
4408              safe to do because any path whose parent has non-inheritable
4409              ranges is always considered a subtree with differing mergeinfo
4410              even if that path has no explicit mergeinfo prior to the
4411              merge -- See condition 3 in the doc string for
4412              merge.c:get_mergeinfo_paths(). */
4413           SVN_ERR(svn_rangelist_intersect(&explicit_rangelist,
4414                                           target_rangelist,
4415                                           requested_rangelist,
4416                                           FALSE, scratch_pool));
4417         }
4418       else
4419         {
4420           explicit_rangelist =
4421             apr_array_make(result_pool, 0, sizeof(svn_merge_range_t *));
4422         }
4423
4424       /* Was any part of the requested reverse merge not accounted for in
4425          CHILD's explicit or inherited mergeinfo? */
4426       SVN_ERR(svn_rangelist_diff(&deleted_rangelist, &added_rangelist,
4427                                  requested_rangelist, explicit_rangelist,
4428                                  FALSE, scratch_pool));
4429
4430       if (deleted_rangelist->nelts == 0)
4431         {
4432           /* The whole of REVISION1:REVISION2 was represented in CHILD's
4433              explicit/inherited mergeinfo, allocate CHILD's remaining
4434              ranges in POOL and then we are done. */
4435           SVN_ERR(svn_rangelist_reverse(requested_rangelist, scratch_pool));
4436           child->remaining_ranges = svn_rangelist_dup(requested_rangelist,
4437                                                       result_pool);
4438         }
4439       else /* We need to check CHILD's implicit mergeinfo. */
4440         {
4441           svn_rangelist_t *implicit_rangelist;
4442
4443           SVN_ERR(ensure_implicit_mergeinfo(parent,
4444                                             child,
4445                                             child_inherits_implicit,
4446                                             revision1,
4447                                             revision2,
4448                                             ra_session,
4449                                             ctx,
4450                                             result_pool,
4451                                             scratch_pool));
4452
4453           target_implicit_rangelist = svn_hash_gets(child->implicit_mergeinfo,
4454                                                     mergeinfo_path);
4455
4456           if (target_implicit_rangelist)
4457             SVN_ERR(svn_rangelist_intersect(&implicit_rangelist,
4458                                             target_implicit_rangelist,
4459                                             requested_rangelist,
4460                                             FALSE, scratch_pool));
4461           else
4462             implicit_rangelist = apr_array_make(scratch_pool, 0,
4463                                                 sizeof(svn_merge_range_t *));
4464
4465           SVN_ERR(svn_rangelist_merge2(implicit_rangelist,
4466                                        explicit_rangelist, scratch_pool,
4467                                        scratch_pool));
4468           SVN_ERR(svn_rangelist_reverse(implicit_rangelist, scratch_pool));
4469           child->remaining_ranges = svn_rangelist_dup(implicit_rangelist,
4470                                                       result_pool);
4471         }
4472     }
4473   else /* This is a forward merge */
4474     {
4475       /* Set EXPLICIT_RANGELIST to the list of source-range revs that are
4476          NOT already recorded as merged to target. */
4477       if (target_rangelist)
4478         {
4479           /* See earlier comment preceding svn_rangelist_intersect() for
4480              why we don't consider inheritance here. */
4481           SVN_ERR(svn_rangelist_remove(&explicit_rangelist,
4482                                        target_rangelist,
4483                                        requested_rangelist, FALSE,
4484                                        scratch_pool));
4485         }
4486       else
4487         {
4488           explicit_rangelist = svn_rangelist_dup(requested_rangelist,
4489                                                  scratch_pool);
4490         }
4491
4492       if (explicit_rangelist->nelts == 0)
4493         {
4494           child->remaining_ranges =
4495             apr_array_make(result_pool, 0, sizeof(svn_merge_range_t *));
4496         }
4497       else
4498 /* ### TODO:  Which evil shall we choose?
4499    ###
4500    ### If we allow all forward-merges not already found in recorded
4501    ### mergeinfo, we destroy the ability to, say, merge the whole of a
4502    ### branch to the trunk while automatically ignoring the revisions
4503    ### common to both.  That's bad.
4504    ###
4505    ### If we allow only forward-merges not found in either recorded
4506    ### mergeinfo or implicit mergeinfo (natural history), then the
4507    ### previous scenario works great, but we can't reverse-merge a
4508    ### previous change made to our line of history and then remake it
4509    ### (because the reverse-merge will leave no mergeinfo trace, and
4510    ### the remake-it attempt will still find the original change in
4511    ### natural mergeinfo.  But you know, that we happen to use 'merge'
4512    ### for revision undoing is somewhat unnatural anyway, so I'm
4513    ### finding myself having little interest in caring too much about
4514    ### this.  That said, if we had a way of storing reverse merge
4515    ### ranges, we'd be in good shape either way.
4516 */
4517 #ifdef SVN_MERGE__ALLOW_ALL_FORWARD_MERGES_FROM_SELF
4518         {
4519           /* ### Don't consider implicit mergeinfo. */
4520           child->remaining_ranges = svn_rangelist_dup(explicit_rangelist,
4521                                                       pool);
4522         }
4523 #else
4524         {
4525           /* Based on CHILD's TARGET_MERGEINFO there are ranges to merge.
4526              Check CHILD's implicit mergeinfo to see if these remaining
4527              ranges are represented there. */
4528           SVN_ERR(ensure_implicit_mergeinfo(parent,
4529                                             child,
4530                                             child_inherits_implicit,
4531                                             revision1,
4532                                             revision2,
4533                                             ra_session,
4534                                             ctx,
4535                                             result_pool,
4536                                             scratch_pool));
4537
4538           target_implicit_rangelist = svn_hash_gets(child->implicit_mergeinfo,
4539                                                     mergeinfo_path);
4540           if (target_implicit_rangelist)
4541             SVN_ERR(svn_rangelist_remove(&(child->remaining_ranges),
4542                                          target_implicit_rangelist,
4543                                          explicit_rangelist,
4544                                          FALSE, result_pool));
4545           else
4546             child->remaining_ranges = svn_rangelist_dup(explicit_rangelist,
4547                                                         result_pool);
4548         }
4549 #endif
4550     }
4551
4552   return SVN_NO_ERROR;
4553 }
4554
4555 /* Helper for do_file_merge and do_directory_merge (by way of
4556    populate_remaining_ranges() for the latter).
4557
4558    Determine what portions of SOURCE have already
4559    been merged to CHILD->ABSPATH and populate CHILD->REMAINING_RANGES with
4560    the ranges that still need merging.
4561
4562    SOURCE and CTX are all cascaded from the caller's arguments of the same
4563    names.  Note that this means SOURCE adheres to the requirements noted in
4564    `MERGEINFO MERGE SOURCE NORMALIZATION'.
4565
4566    CHILD represents a working copy path which is the merge target or one of
4567    the target's subtrees.  If not NULL, PARENT is CHILD's nearest path-wise
4568    ancestor - see 'THE CHILDREN_WITH_MERGEINFO ARRAY'.  TARGET_MERGEINFO is
4569    the working mergeinfo on CHILD.
4570
4571    RA_SESSION is the session for the younger of SOURCE->loc1 and
4572    SOURCE->loc2.
4573
4574    If the function needs to consider CHILD->IMPLICIT_MERGEINFO and
4575    CHILD_INHERITS_IMPLICIT is true, then set CHILD->IMPLICIT_MERGEINFO to the
4576    mergeinfo inherited from PARENT->IMPLICIT_MERGEINFO.  Otherwise contact
4577    the repository for CHILD->IMPLICIT_MERGEINFO.
4578
4579    If not null, IMPLICIT_SRC_GAP is the gap, if any, in the natural history
4580    of SOURCE, see merge_cmd_baton_t.implicit_src_gap.
4581
4582    SCRATCH_POOL is used for all temporary allocations.  Changes to CHILD and
4583    PARENT are made in RESULT_POOL.
4584
4585    NOTE: This should only be called when honoring mergeinfo.
4586
4587    NOTE: If PARENT is present then this function must have previously been
4588    called for PARENT, i.e. if populate_remaining_ranges() is calling this
4589    function for a set of svn_client__merge_path_t* the calls must be made
4590    in depth-first order.
4591
4592    NOTE: When performing reverse merges, return
4593    SVN_ERR_CLIENT_NOT_READY_TO_MERGE if both locations in SOURCE and
4594    CHILD->ABSPATH are all on the same line of history but CHILD->ABSPATH's
4595    base revision is older than the SOURCE->rev1:rev2 range, see comment re
4596    issue #2973 below.
4597 */
4598 static svn_error_t *
4599 calculate_remaining_ranges(svn_client__merge_path_t *parent,
4600                            svn_client__merge_path_t *child,
4601                            const merge_source_t *source,
4602                            svn_mergeinfo_t target_mergeinfo,
4603                            const apr_array_header_t *implicit_src_gap,
4604                            svn_boolean_t child_inherits_implicit,
4605                            svn_ra_session_t *ra_session,
4606                            svn_client_ctx_t *ctx,
4607                            apr_pool_t *result_pool,
4608                            apr_pool_t *scratch_pool)
4609 {
4610   const svn_client__pathrev_t *primary_src
4611     = (source->loc1->rev < source->loc2->rev) ? source->loc2 : source->loc1;
4612   const char *mergeinfo_path = svn_client__pathrev_fspath(primary_src,
4613                                                           scratch_pool);
4614   /* Intersection of TARGET_MERGEINFO and the merge history
4615      described by SOURCE. */
4616   svn_rangelist_t *target_rangelist;
4617   svn_revnum_t child_base_revision;
4618
4619   /* Since this function should only be called when honoring mergeinfo and
4620    * SOURCE adheres to the requirements noted in 'MERGEINFO MERGE SOURCE
4621    * NORMALIZATION', SOURCE must be 'ancestral'. */
4622   SVN_ERR_ASSERT(source->ancestral);
4623
4624   /* Determine which of the requested ranges to consider merging... */
4625
4626   /* Set TARGET_RANGELIST to the portion of TARGET_MERGEINFO that refers
4627      to SOURCE (excluding any gap in SOURCE): first get all ranges from
4628      TARGET_MERGEINFO that refer to the path of SOURCE, and then prune
4629      any ranges that lie in the gap in SOURCE.
4630
4631      ### [JAF] In fact, that may still leave some ranges that lie entirely
4632      outside the range of SOURCE; it seems we don't care about that.  */
4633   if (target_mergeinfo)
4634     target_rangelist = svn_hash_gets(target_mergeinfo, mergeinfo_path);
4635   else
4636     target_rangelist = NULL;
4637   if (implicit_src_gap && target_rangelist)
4638     {
4639       /* Remove any mergeinfo referring to the 'gap' in SOURCE, as that
4640          mergeinfo doesn't really refer to SOURCE at all but instead
4641          refers to locations that are non-existent or on a different
4642          line of history.  (Issue #3242.) */
4643       SVN_ERR(svn_rangelist_remove(&target_rangelist,
4644                                    implicit_src_gap, target_rangelist,
4645                                    FALSE, result_pool));
4646     }
4647
4648   /* Initialize CHILD->REMAINING_RANGES and filter out revisions already
4649      merged (or, in the case of reverse merges, ranges not yet merged). */
4650   SVN_ERR(filter_merged_revisions(parent, child, mergeinfo_path,
4651                                   target_rangelist,
4652                                   source->loc1->rev, source->loc2->rev,
4653                                   child_inherits_implicit,
4654                                   ra_session, ctx, result_pool,
4655                                   scratch_pool));
4656
4657   /* Issue #2973 -- from the continuing series of "Why, since the advent of
4658      merge tracking, allowing merges into mixed rev and locally modified
4659      working copies isn't simple and could be considered downright evil".
4660
4661      If reverse merging a range to the WC path represented by CHILD, from
4662      that path's own history, where the path inherits no locally modified
4663      mergeinfo from its WC parents (i.e. there is no uncommitted merge to
4664      the WC), and the path's base revision is older than the range, then
4665      the merge will always be a no-op.  This is because we only allow reverse
4666      merges of ranges in the path's explicit or natural mergeinfo and a
4667      reverse merge from the path's future history obviously isn't going to be
4668      in either, hence the no-op.
4669
4670      The problem is two-fold.  First, in a mixed rev WC, the change we
4671      want to revert might actually be to some child of the target path
4672      which is at a younger base revision.  Sure, we can merge directly
4673      to that child or update the WC or even use --ignore-ancestry and then
4674      successfully run the reverse merge, but that gets to the second
4675      problem: Those courses of action are not very obvious.  Before 1.5 if
4676      a user committed a change that didn't touch the commit target, then
4677      immediately decided to revert that change via a reverse merge it would
4678      just DTRT.  But with the advent of merge tracking the user gets a no-op.
4679
4680      So in the name of user friendliness, return an error suggesting a helpful
4681      course of action.
4682   */
4683   SVN_ERR(svn_wc__node_get_base(NULL, &child_base_revision,
4684                                 NULL, NULL, NULL, NULL,
4685                                 ctx->wc_ctx, child->abspath,
4686                                 TRUE /* ignore_enoent */,
4687                                 FALSE /* show_hidden */,
4688                                 scratch_pool, scratch_pool));
4689   /* If CHILD has no base revision then it hasn't been committed yet, so it
4690      can't have any "future" history. */
4691   if (SVN_IS_VALID_REVNUM(child_base_revision)
4692       && ((child->remaining_ranges)->nelts == 0) /* Inoperative merge */
4693       && (source->loc2->rev < source->loc1->rev)     /* Reverse merge */
4694       && (child_base_revision <= source->loc2->rev))  /* From CHILD's future */
4695     {
4696       /* Hmmm, an inoperative reverse merge from the "future".  If it is
4697          from our own future return a helpful error. */
4698       svn_error_t *err;
4699       svn_client__pathrev_t *start_loc;
4700
4701       err = svn_client__repos_location(&start_loc,
4702                                        ra_session,
4703                                        source->loc1,
4704                                        child_base_revision,
4705                                        ctx, scratch_pool, scratch_pool);
4706       if (err)
4707         {
4708           if (err->apr_err == SVN_ERR_FS_NOT_FOUND
4709               || err->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES)
4710             svn_error_clear(err);
4711           else
4712             return svn_error_trace(err);
4713         }
4714       else
4715         {
4716           const char *url;
4717
4718           SVN_ERR(svn_wc__node_get_url(&url, ctx->wc_ctx, child->abspath,
4719                                        scratch_pool, scratch_pool));
4720           if (strcmp(start_loc->url, url) == 0)
4721             return svn_error_create(SVN_ERR_CLIENT_MERGE_UPDATE_REQUIRED, NULL,
4722                                     _("Cannot reverse-merge a range from a "
4723                                       "path's own future history; try "
4724                                       "updating first"));
4725         }
4726     }
4727
4728   return SVN_NO_ERROR;
4729 }
4730
4731 /* Helper for populate_remaining_ranges().
4732
4733    SOURCE is cascaded from the arguments of the same name in
4734    populate_remaining_ranges().
4735
4736    Note: The following comments assume a forward merge, i.e.
4737    SOURCE->loc1->rev < SOURCE->loc2->rev.  If this is a reverse merge then
4738    all the following comments still apply, but with SOURCE->loc1 switched
4739    with SOURCE->loc2.
4740
4741    Like populate_remaining_ranges(), SOURCE must adhere to the restrictions
4742    documented in 'MERGEINFO MERGE SOURCE NORMALIZATION'.  These restrictions
4743    allow for a *single* gap in SOURCE, GAP_REV1:GAP_REV2 exclusive:inclusive
4744    (where SOURCE->loc1->rev == GAP_REV1 <= GAP_REV2 < SOURCE->loc2->rev),
4745    if SOURCE->loc2->url@(GAP_REV2+1) was copied from SOURCE->loc1.  If such
4746    a gap exists, set *GAP_START and *GAP_END to the starting and ending
4747    revisions of the gap.  Otherwise set both to SVN_INVALID_REVNUM.
4748
4749    For example, if the natural history of URL@2:URL@9 is 'trunk/:2,7-9' this
4750    would indicate that trunk@7 was copied from trunk@2.  This function would
4751    return GAP_START:GAP_END of 2:6 in this case.  Note that a path 'trunk'
4752    might exist at r3-6, but it would not be on the same line of history as
4753    trunk@9.
4754
4755    ### GAP_START is basically redundant, as (if there is a gap at all) it is
4756    necessarily the older revision of SOURCE.
4757
4758    RA_SESSION is an open RA session to the repository in which SOURCE lives.
4759 */
4760 static svn_error_t *
4761 find_gaps_in_merge_source_history(svn_revnum_t *gap_start,
4762                                   svn_revnum_t *gap_end,
4763                                   const merge_source_t *source,
4764                                   svn_ra_session_t *ra_session,
4765                                   svn_client_ctx_t *ctx,
4766                                   apr_pool_t *scratch_pool)
4767 {
4768   svn_mergeinfo_t implicit_src_mergeinfo;
4769   svn_revnum_t old_rev = MIN(source->loc1->rev, source->loc2->rev);
4770   const svn_client__pathrev_t *primary_src
4771     = (source->loc1->rev < source->loc2->rev) ? source->loc2 : source->loc1;
4772   const char *merge_src_fspath = svn_client__pathrev_fspath(primary_src,
4773                                                             scratch_pool);
4774   svn_rangelist_t *rangelist;
4775
4776   SVN_ERR_ASSERT(source->ancestral);
4777
4778   /* Start by assuming there is no gap. */
4779   *gap_start = *gap_end = SVN_INVALID_REVNUM;
4780
4781   /* Easy out: There can't be a gap between adjacent revisions. */
4782   if (abs(source->loc1->rev - source->loc2->rev) == 1)
4783     return SVN_NO_ERROR;
4784
4785   /* Get SOURCE as mergeinfo. */
4786   SVN_ERR(svn_client__get_history_as_mergeinfo(&implicit_src_mergeinfo, NULL,
4787                                                primary_src,
4788                                                primary_src->rev, old_rev,
4789                                                ra_session,
4790                                                ctx, scratch_pool));
4791
4792   rangelist = svn_hash_gets(implicit_src_mergeinfo, merge_src_fspath);
4793
4794   if (!rangelist) /* ### Can we ever not find a rangelist? */
4795     return SVN_NO_ERROR;
4796
4797   /* A gap in natural history can result from either a copy or
4798      a rename.  If from a copy then history as mergeinfo will look
4799      something like this:
4800
4801        '/trunk:X,Y-Z'
4802
4803      If from a rename it will look like this:
4804
4805        '/trunk_old_name:X'
4806        '/trunk_new_name:Y-Z'
4807
4808     In both cases the gap, if it exists, is M-N, where M = X + 1 and
4809     N = Y - 1.
4810
4811     Note that per the rules of 'MERGEINFO MERGE SOURCE NORMALIZATION' we
4812     should never have multiple gaps, e.g. if we see anything like the
4813     following then something is quite wrong:
4814
4815         '/trunk_old_name:A,B-C'
4816         '/trunk_new_name:D-E'
4817   */
4818
4819   if (rangelist->nelts > 1) /* Copy */
4820     {
4821       const svn_merge_range_t *gap;
4822       /* As mentioned above, multiple gaps *shouldn't* be possible. */
4823       SVN_ERR_ASSERT(apr_hash_count(implicit_src_mergeinfo) == 1);
4824
4825       gap = APR_ARRAY_IDX(rangelist, rangelist->nelts - 1,
4826                           const svn_merge_range_t *);
4827
4828       *gap_start = MIN(source->loc1->rev, source->loc2->rev);
4829       *gap_end = gap->start;
4830
4831       /* ### Issue #4132:
4832          ### This assertion triggers in merge_tests.py svnmucc_abuse_1()
4833          ### when a node is replaced by an older copy of itself.
4834
4835          BH: I think we should review this and the 'rename' case to find
4836              out which behavior we really want, and if we can really
4837              determine what happened this way. */
4838       SVN_ERR_ASSERT(*gap_start < *gap_end);
4839     }
4840   else if (apr_hash_count(implicit_src_mergeinfo) > 1) /* Rename */
4841     {
4842       svn_rangelist_t *requested_rangelist =
4843         svn_rangelist__initialize(MIN(source->loc1->rev, source->loc2->rev),
4844                                   MAX(source->loc1->rev, source->loc2->rev),
4845                                   TRUE, scratch_pool);
4846       svn_rangelist_t *implicit_rangelist =
4847         apr_array_make(scratch_pool, 2, sizeof(svn_merge_range_t *));
4848       svn_rangelist_t *gap_rangelist;
4849
4850       SVN_ERR(svn_rangelist__merge_many(implicit_rangelist,
4851                                         implicit_src_mergeinfo,
4852                                         scratch_pool, scratch_pool));
4853       SVN_ERR(svn_rangelist_remove(&gap_rangelist, implicit_rangelist,
4854                                    requested_rangelist, FALSE,
4855                                    scratch_pool));
4856
4857       /* If there is anything left it is the gap. */
4858       if (gap_rangelist->nelts)
4859         {
4860           svn_merge_range_t *gap_range =
4861             APR_ARRAY_IDX(gap_rangelist, 0, svn_merge_range_t *);
4862
4863           *gap_start = gap_range->start;
4864           *gap_end = gap_range->end;
4865         }
4866     }
4867
4868   SVN_ERR_ASSERT(*gap_start == MIN(source->loc1->rev, source->loc2->rev)
4869                  || (*gap_start == SVN_INVALID_REVNUM
4870                      && *gap_end == SVN_INVALID_REVNUM));
4871   return SVN_NO_ERROR;
4872 }
4873
4874 /* Helper for do_directory_merge().
4875
4876    For each (svn_client__merge_path_t *) child in CHILDREN_WITH_MERGEINFO,
4877    populate that child's 'remaining_ranges' list with (### ... what?),
4878    and populate that child's 'implicit_mergeinfo' with its implicit
4879    mergeinfo (natural history).  CHILDREN_WITH_MERGEINFO is expected
4880    to be sorted in depth first order and each child must be processed in
4881    that order.  The inheritability of all calculated ranges is TRUE.
4882
4883    If mergeinfo is being honored (based on MERGE_B -- see HONOR_MERGEINFO()
4884    for how this is determined), this function will actually try to be
4885    intelligent about populating remaining_ranges list.  Otherwise, it
4886    will claim that each child has a single remaining range, from
4887    SOURCE->rev1, to SOURCE->rev2.
4888    ### We also take the short-cut if doing record-only.  Why?
4889
4890    SCRATCH_POOL is used for all temporary allocations.  Changes to
4891    CHILDREN_WITH_MERGEINFO are made in RESULT_POOL.
4892
4893    Note that if SOURCE->rev1 > SOURCE->rev2, then each child's remaining_ranges
4894    member does not adhere to the API rules for rangelists described in
4895    svn_mergeinfo.h -- See svn_client__merge_path_t.
4896
4897    See `MERGEINFO MERGE SOURCE NORMALIZATION' for more requirements
4898    around SOURCE.
4899 */
4900 static svn_error_t *
4901 populate_remaining_ranges(apr_array_header_t *children_with_mergeinfo,
4902                           const merge_source_t *source,
4903                           svn_ra_session_t *ra_session,
4904                           merge_cmd_baton_t *merge_b,
4905                           apr_pool_t *result_pool,
4906                           apr_pool_t *scratch_pool)
4907 {
4908   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
4909   int i;
4910   svn_revnum_t gap_start, gap_end;
4911
4912   /* If we aren't honoring mergeinfo or this is a --record-only merge,
4913      we'll make quick work of this by simply adding dummy SOURCE->rev1:rev2
4914      ranges for all children. */
4915   if (! HONOR_MERGEINFO(merge_b) || merge_b->record_only)
4916     {
4917       for (i = 0; i < children_with_mergeinfo->nelts; i++)
4918         {
4919           svn_client__merge_path_t *child =
4920             APR_ARRAY_IDX(children_with_mergeinfo, i,
4921                           svn_client__merge_path_t *);
4922
4923           svn_pool_clear(iterpool);
4924
4925           /* Issue #3646 'record-only merges create self-referential
4926              mergeinfo'.  Get the merge target's implicit mergeinfo (natural
4927              history).  We'll use it later to avoid setting self-referential
4928              mergeinfo -- see filter_natural_history_from_mergeinfo(). */
4929           if (i == 0) /* First item is always the merge target. */
4930             {
4931               SVN_ERR(get_full_mergeinfo(NULL, /* child->pre_merge_mergeinfo */
4932                                          &(child->implicit_mergeinfo),
4933                                          NULL, /* child->inherited_mergeinfo */
4934                                          svn_mergeinfo_inherited, ra_session,
4935                                          child->abspath,
4936                                          MAX(source->loc1->rev,
4937                                              source->loc2->rev),
4938                                          MIN(source->loc1->rev,
4939                                              source->loc2->rev),
4940                                          merge_b->ctx, result_pool,
4941                                          iterpool));
4942             }
4943           else
4944             {
4945               /* Issue #3443 - Subtrees of the merge target can inherit
4946                  their parent's implicit mergeinfo in most cases. */
4947               svn_client__merge_path_t *parent
4948                 = find_nearest_ancestor(children_with_mergeinfo,
4949                                         FALSE, child->abspath);
4950               svn_boolean_t child_inherits_implicit;
4951
4952               /* If CHILD is a subtree then its parent must be in
4953                  CHILDREN_WITH_MERGEINFO, see the global comment
4954                  'THE CHILDREN_WITH_MERGEINFO ARRAY'. */
4955               SVN_ERR_ASSERT(parent);
4956
4957               child_inherits_implicit = (parent && !child->switched);
4958               SVN_ERR(ensure_implicit_mergeinfo(parent, child,
4959                                                 child_inherits_implicit,
4960                                                 source->loc1->rev,
4961                                                 source->loc2->rev,
4962                                                 ra_session, merge_b->ctx,
4963                                                 result_pool, iterpool));
4964             }
4965
4966           child->remaining_ranges = svn_rangelist__initialize(source->loc1->rev,
4967                                                               source->loc2->rev,
4968                                                               TRUE,
4969                                                               result_pool);
4970         }
4971       svn_pool_destroy(iterpool);
4972       return SVN_NO_ERROR;
4973     }
4974
4975   /* If, in the merge source's history, there was a copy from an older
4976      revision, then SOURCE->loc2->url won't exist at some range M:N, where
4977      SOURCE->loc1->rev < M < N < SOURCE->loc2->rev. The rules of 'MERGEINFO
4978      MERGE SOURCE NORMALIZATION' allow this, but we must ignore these gaps
4979      when calculating what ranges remain to be merged from SOURCE. If we
4980      don't and try to merge any part of SOURCE->loc2->url@M:N we would
4981      break the editor since no part of that actually exists.  See
4982      http://svn.haxx.se/dev/archive-2008-11/0618.shtml.
4983
4984      Find the gaps in the merge target's history, if any.  Eventually
4985      we will adjust CHILD->REMAINING_RANGES such that we don't describe
4986      non-existent paths to the editor. */
4987   SVN_ERR(find_gaps_in_merge_source_history(&gap_start, &gap_end,
4988                                             source,
4989                                             ra_session, merge_b->ctx,
4990                                             iterpool));
4991
4992   /* Stash any gap in the merge command baton, we'll need it later when
4993      recording mergeinfo describing this merge. */
4994   if (SVN_IS_VALID_REVNUM(gap_start) && SVN_IS_VALID_REVNUM(gap_end))
4995     merge_b->implicit_src_gap = svn_rangelist__initialize(gap_start, gap_end,
4996                                                           TRUE, result_pool);
4997
4998   for (i = 0; i < children_with_mergeinfo->nelts; i++)
4999     {
5000       svn_client__merge_path_t *child =
5001         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
5002       const char *child_repos_path
5003         = svn_dirent_skip_ancestor(merge_b->target->abspath, child->abspath);
5004       merge_source_t child_source;
5005       svn_client__merge_path_t *parent = NULL;
5006       svn_boolean_t child_inherits_implicit;
5007
5008       svn_pool_clear(iterpool);
5009
5010       /* If the path is absent don't do subtree merge either. */
5011       SVN_ERR_ASSERT(child);
5012       if (child->absent)
5013         continue;
5014
5015       SVN_ERR_ASSERT(child_repos_path != NULL);
5016       child_source.loc1 = svn_client__pathrev_join_relpath(
5017                             source->loc1, child_repos_path, iterpool);
5018       child_source.loc2 = svn_client__pathrev_join_relpath(
5019                             source->loc2, child_repos_path, iterpool);
5020       /* ### Is the child 'ancestral' over the same revision range?  It's
5021        * not necessarily true that a child is 'ancestral' if the parent is,
5022        * nor that it's not if the parent is not.  However, here we claim
5023        * that it is.  Before we had this 'ancestral' field that we need to
5024        * set explicitly, the claim was implicit.  Either way, the impact is
5025        * that we might pass calculate_remaining_ranges() a source that is
5026        * not in fact 'ancestral' (despite its 'ancestral' field being true),
5027        * contrary to its doc-string. */
5028       child_source.ancestral = source->ancestral;
5029
5030       /* Get the explicit/inherited mergeinfo for CHILD.  If CHILD is the
5031          merge target then also get its implicit mergeinfo.  Otherwise defer
5032          this until we know it is absolutely necessary, since it requires an
5033          expensive round trip communication with the server. */
5034       SVN_ERR(get_full_mergeinfo(
5035         child->pre_merge_mergeinfo ? NULL : &(child->pre_merge_mergeinfo),
5036         /* Get implicit only for merge target. */
5037         (i == 0) ? &(child->implicit_mergeinfo) : NULL,
5038         &(child->inherited_mergeinfo),
5039         svn_mergeinfo_inherited, ra_session,
5040         child->abspath,
5041         MAX(source->loc1->rev, source->loc2->rev),
5042         MIN(source->loc1->rev, source->loc2->rev),
5043         merge_b->ctx, result_pool, iterpool));
5044
5045       /* If CHILD isn't the merge target find its parent. */
5046       if (i > 0)
5047         {
5048           parent = find_nearest_ancestor(children_with_mergeinfo,
5049                                          FALSE, child->abspath);
5050           /* If CHILD is a subtree then its parent must be in
5051              CHILDREN_WITH_MERGEINFO, see the global comment
5052              'THE CHILDREN_WITH_MERGEINFO ARRAY'. */
5053           SVN_ERR_ASSERT(parent);
5054         }
5055
5056       /* Issue #3443 - Can CHILD inherit PARENT's implicit mergeinfo, saving
5057          us from having to ask the repos?  The only time we can't do this is if
5058          CHILD is the merge target and so there is no PARENT to inherit from
5059          or if CHILD is the root of a switched subtree, in which case PARENT
5060          exists but is not CHILD's repository parent. */
5061       child_inherits_implicit = (parent && !child->switched);
5062
5063       SVN_ERR(calculate_remaining_ranges(parent, child,
5064                                          &child_source,
5065                                          child->pre_merge_mergeinfo,
5066                                          merge_b->implicit_src_gap,
5067                                          child_inherits_implicit,
5068                                          ra_session,
5069                                          merge_b->ctx, result_pool,
5070                                          iterpool));
5071
5072       /* Deal with any gap in SOURCE's natural history.
5073
5074          If the gap is a proper subset of CHILD->REMAINING_RANGES then we can
5075          safely ignore it since we won't describe this path/rev pair.
5076
5077          If the gap exactly matches or is a superset of a range in
5078          CHILD->REMAINING_RANGES then we must remove that range so we don't
5079          attempt to describe non-existent paths via the reporter, this will
5080          break the editor and our merge.
5081
5082          If the gap adjoins or overlaps a range in CHILD->REMAINING_RANGES
5083          then we must *add* the gap so we span the missing revisions. */
5084       if (child->remaining_ranges->nelts
5085           && merge_b->implicit_src_gap)
5086         {
5087           int j;
5088           svn_boolean_t proper_subset = FALSE;
5089           svn_boolean_t overlaps_or_adjoins = FALSE;
5090
5091           /* If this is a reverse merge reorder CHILD->REMAINING_RANGES
5092               so it will work with the svn_rangelist_* APIs below. */
5093           if (source->loc1->rev > source->loc2->rev)
5094             SVN_ERR(svn_rangelist_reverse(child->remaining_ranges, iterpool));
5095
5096           for (j = 0; j < child->remaining_ranges->nelts; j++)
5097             {
5098               svn_merge_range_t *range
5099                 = APR_ARRAY_IDX(child->remaining_ranges, j, svn_merge_range_t *);
5100
5101               if ((range->start <= gap_start && gap_end < range->end)
5102                   || (range->start < gap_start && gap_end <= range->end))
5103                 {
5104                   proper_subset = TRUE;
5105                   break;
5106                 }
5107               else if ((gap_start == range->start) && (range->end == gap_end))
5108                 {
5109                   break;
5110                 }
5111               else if (gap_start <= range->end && range->start <= gap_end)
5112                 /* intersect */
5113                 {
5114                   overlaps_or_adjoins = TRUE;
5115                   break;
5116                 }
5117             }
5118
5119           if (!proper_subset)
5120             {
5121               /* We need to make adjustments.  Remove from, or add the gap
5122                  to, CHILD->REMAINING_RANGES as appropriate. */
5123
5124               if (overlaps_or_adjoins)
5125                 SVN_ERR(svn_rangelist_merge2(child->remaining_ranges,
5126                                              merge_b->implicit_src_gap,
5127                                              result_pool, iterpool));
5128               else /* equals == TRUE */
5129                 SVN_ERR(svn_rangelist_remove(&(child->remaining_ranges),
5130                                              merge_b->implicit_src_gap,
5131                                              child->remaining_ranges, FALSE,
5132                                              result_pool));
5133             }
5134
5135           if (source->loc1->rev > source->loc2->rev) /* Reverse merge */
5136             SVN_ERR(svn_rangelist_reverse(child->remaining_ranges, iterpool));
5137         }
5138     }
5139
5140   svn_pool_destroy(iterpool);
5141   return SVN_NO_ERROR;
5142 }
5143
5144
5145 /*-----------------------------------------------------------------------*/
5146 \f
5147 /*** Other Helper Functions ***/
5148
5149 /* Calculate the new mergeinfo for the target tree rooted at TARGET_ABSPATH
5150    based on MERGES (a mapping of absolute WC paths to rangelists representing
5151    a merge from the source SOURCE_FSPATH).
5152
5153    If RESULT_CATALOG is NULL, then record the new mergeinfo in the WC (at,
5154    and possibly below, TARGET_ABSPATH).
5155
5156    If RESULT_CATALOG is not NULL, then don't record the new mergeinfo on the
5157    WC, but instead record it in RESULT_CATALOG, where the keys are absolute
5158    working copy paths and the values are the new mergeinfos for each.
5159    Allocate additions to RESULT_CATALOG in pool which RESULT_CATALOG was
5160    created in. */
5161 static svn_error_t *
5162 update_wc_mergeinfo(svn_mergeinfo_catalog_t result_catalog,
5163                     const char *target_abspath,
5164                     const char *source_fspath,
5165                     apr_hash_t *merges,
5166                     svn_boolean_t is_rollback,
5167                     svn_client_ctx_t *ctx,
5168                     apr_pool_t *scratch_pool)
5169 {
5170   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
5171   apr_hash_index_t *hi;
5172
5173   /* Combine the mergeinfo for the revision range just merged into
5174      the WC with its on-disk mergeinfo. */
5175   for (hi = apr_hash_first(scratch_pool, merges); hi; hi = apr_hash_next(hi))
5176     {
5177       const char *local_abspath = svn__apr_hash_index_key(hi);
5178       svn_rangelist_t *ranges = svn__apr_hash_index_val(hi);
5179       svn_rangelist_t *rangelist;
5180       svn_error_t *err;
5181       const char *local_abspath_rel_to_target;
5182       const char *fspath;
5183       svn_mergeinfo_t mergeinfo;
5184
5185       svn_pool_clear(iterpool);
5186
5187       /* As some of the merges may've changed the WC's mergeinfo, get
5188          a fresh copy before using it to update the WC's mergeinfo. */
5189       err = svn_client__parse_mergeinfo(&mergeinfo, ctx->wc_ctx,
5190                                         local_abspath, iterpool, iterpool);
5191
5192       /* If a directory PATH was skipped because it is missing or was
5193          obstructed by an unversioned item then there's nothing we can
5194          do with that, so skip it. */
5195       if (err)
5196         {
5197           if (err->apr_err == SVN_ERR_WC_NOT_LOCKED
5198               || err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
5199             {
5200               svn_error_clear(err);
5201               continue;
5202             }
5203           else
5204             {
5205               return svn_error_trace(err);
5206             }
5207         }
5208
5209       /* If we are attempting to set empty revision range override mergeinfo
5210          on a path with no explicit mergeinfo, we first need the
5211          mergeinfo that path inherits. */
5212       if (mergeinfo == NULL && ranges->nelts == 0)
5213         {
5214           SVN_ERR(svn_client__get_wc_mergeinfo(&mergeinfo, NULL,
5215                                                svn_mergeinfo_nearest_ancestor,
5216                                                local_abspath, NULL, NULL,
5217                                                FALSE, ctx, iterpool, iterpool));
5218         }
5219
5220       if (mergeinfo == NULL)
5221         mergeinfo = apr_hash_make(iterpool);
5222
5223       local_abspath_rel_to_target = svn_dirent_skip_ancestor(target_abspath,
5224                                                              local_abspath);
5225       SVN_ERR_ASSERT(local_abspath_rel_to_target != NULL);
5226       fspath = svn_fspath__join(source_fspath,
5227                                 local_abspath_rel_to_target,
5228                                 iterpool);
5229       rangelist = svn_hash_gets(mergeinfo, fspath);
5230       if (rangelist == NULL)
5231         rangelist = apr_array_make(iterpool, 0, sizeof(svn_merge_range_t *));
5232
5233       if (is_rollback)
5234         {
5235           ranges = svn_rangelist_dup(ranges, iterpool);
5236           SVN_ERR(svn_rangelist_reverse(ranges, iterpool));
5237           SVN_ERR(svn_rangelist_remove(&rangelist, ranges, rangelist,
5238                                        FALSE,
5239                                        iterpool));
5240         }
5241       else
5242         {
5243           SVN_ERR(svn_rangelist_merge2(rangelist, ranges, iterpool, iterpool));
5244         }
5245       /* Update the mergeinfo by adjusting the path's rangelist. */
5246       svn_hash_sets(mergeinfo, fspath, rangelist);
5247
5248       if (is_rollback && apr_hash_count(mergeinfo) == 0)
5249         mergeinfo = NULL;
5250
5251       svn_mergeinfo__remove_empty_rangelists(mergeinfo, scratch_pool);
5252
5253       if (result_catalog)
5254         {
5255           svn_mergeinfo_t existing_mergeinfo =
5256             svn_hash_gets(result_catalog, local_abspath);
5257           apr_pool_t *result_catalog_pool = apr_hash_pool_get(result_catalog);
5258
5259           if (existing_mergeinfo)
5260             SVN_ERR(svn_mergeinfo_merge2(mergeinfo, existing_mergeinfo,
5261                                          result_catalog_pool, scratch_pool));
5262           svn_hash_sets(result_catalog,
5263                         apr_pstrdup(result_catalog_pool, local_abspath),
5264                         svn_mergeinfo_dup(mergeinfo, result_catalog_pool));
5265         }
5266       else
5267         {
5268           err = svn_client__record_wc_mergeinfo(local_abspath, mergeinfo,
5269                                                 TRUE, ctx, iterpool);
5270
5271           if (err && err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)
5272             {
5273               /* PATH isn't just missing, it's not even versioned as far
5274                  as this working copy knows.  But it was included in
5275                  MERGES, which means that the server knows about it.
5276                  Likely we don't have access to the source due to authz
5277                  restrictions.  For now just clear the error and
5278                  continue...
5279
5280                  ### TODO:  Set non-inheritable mergeinfo on PATH's immediate
5281                  ### parent and normal mergeinfo on PATH's siblings which we
5282                  ### do have access to. */
5283               svn_error_clear(err);
5284             }
5285           else
5286             SVN_ERR(err);
5287         }
5288     }
5289
5290   svn_pool_destroy(iterpool);
5291   return SVN_NO_ERROR;
5292 }
5293
5294 /* Helper for record_mergeinfo_for_dir_merge().
5295
5296    Record override mergeinfo on any paths skipped during a merge.
5297
5298    Set empty mergeinfo on each path in MERGE_B->SKIPPED_ABSPATHS so the path
5299    does not incorrectly inherit mergeinfo that will later be describing
5300    the merge.
5301
5302    MERGEINFO_PATH and MERGE_B are cascaded from
5303    arguments of the same name in the caller.
5304
5305    IS_ROLLBACK is true if the caller is recording a reverse merge and false
5306    otherwise.  RANGELIST is the set of revisions being merged from
5307    MERGEINFO_PATH to MERGE_B->target. */
5308 static svn_error_t *
5309 record_skips_in_mergeinfo(const char *mergeinfo_path,
5310                           const svn_rangelist_t *rangelist,
5311                           svn_boolean_t is_rollback,
5312                           merge_cmd_baton_t *merge_b,
5313                           apr_pool_t *scratch_pool)
5314 {
5315   apr_hash_index_t *hi;
5316   apr_hash_t *merges;
5317   apr_size_t nbr_skips = apr_hash_count(merge_b->skipped_abspaths);
5318   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
5319
5320   if (nbr_skips == 0)
5321     return SVN_NO_ERROR;
5322
5323   merges = apr_hash_make(scratch_pool);
5324
5325   /* Override the mergeinfo for child paths which weren't actually merged. */
5326   for (hi = apr_hash_first(scratch_pool, merge_b->skipped_abspaths); hi;
5327        hi = apr_hash_next(hi))
5328     {
5329       const char *skipped_abspath = svn__apr_hash_index_key(hi);
5330       svn_wc_notify_state_t obstruction_state;
5331
5332       svn_pool_clear(iterpool);
5333
5334       /* Before we override, make sure this is a versioned path, it might
5335          be an external or missing from disk due to authz restrictions. */
5336       SVN_ERR(perform_obstruction_check(&obstruction_state, NULL, NULL,
5337                                         NULL, NULL,
5338                                         merge_b, skipped_abspath,
5339                                         iterpool));
5340       if (obstruction_state == svn_wc_notify_state_obstructed
5341           || obstruction_state == svn_wc_notify_state_missing)
5342         continue;
5343
5344       /* Add an empty range list for this path.
5345
5346          ### TODO: This works fine for a file path skipped because it is
5347          ### missing as long as the file's parent directory is present.
5348          ### But missing directory paths skipped are not handled yet,
5349          ### see issue #2915.
5350
5351          ### TODO: An empty range is fine if the skipped path doesn't
5352          ### inherit any mergeinfo from a parent, but if it does
5353          ### we need to account for that.  See issue #3440
5354          ### http://subversion.tigris.org/issues/show_bug.cgi?id=3440. */
5355       svn_hash_sets(merges, skipped_abspath,
5356                     apr_array_make(scratch_pool, 0,
5357                                    sizeof(svn_merge_range_t *)));
5358
5359       /* if (nbr_skips < notify_b->nbr_notifications)
5360            ### Use RANGELIST as the mergeinfo for all children of
5361            ### this path which were not also explicitly
5362            ### skipped? */
5363     }
5364   SVN_ERR(update_wc_mergeinfo(NULL, merge_b->target->abspath,
5365                               mergeinfo_path, merges,
5366                               is_rollback, merge_b->ctx, iterpool));
5367   svn_pool_destroy(iterpool);
5368   return SVN_NO_ERROR;
5369 }
5370
5371 /* Data for reporting when a merge aborted because of raising conflicts.
5372  */
5373 typedef struct single_range_conflict_report_t
5374 {
5375   /* What sub-range of the requested source raised conflicts?
5376    * The 'inheritable' flag is ignored. */
5377   merge_source_t *conflicted_range;
5378   /* What sub-range of the requested source remains to be merged?
5379    * NULL if no more.  The 'inheritable' flag is ignored. */
5380   merge_source_t *remaining_source;
5381
5382 } single_range_conflict_report_t;
5383
5384 /* Create a single_range_conflict_report_t, containing deep copies of
5385  * CONFLICTED_RANGE and REMAINING_SOURCE, allocated in RESULT_POOL. */
5386 static single_range_conflict_report_t *
5387 single_range_conflict_report_create(const merge_source_t *conflicted_range,
5388                                     const merge_source_t *remaining_source,
5389                                     apr_pool_t *result_pool)
5390 {
5391   single_range_conflict_report_t *report
5392     = apr_palloc(result_pool, sizeof(*report));
5393
5394   assert(conflicted_range != NULL);
5395
5396   report->conflicted_range = merge_source_dup(conflicted_range, result_pool);
5397   report->remaining_source
5398     = remaining_source ? merge_source_dup(remaining_source, result_pool)
5399                        : NULL;
5400   return report;
5401 }
5402
5403 /* Data for reporting when a merge aborted because of raising conflicts.
5404  *
5405  * ### TODO: More info, including the ranges (or other parameters) the user
5406  *     needs to complete the merge.
5407  */
5408 typedef struct conflict_report_t
5409 {
5410   const char *target_abspath;
5411   /* The revision range during which conflicts were raised */
5412   const merge_source_t *conflicted_range;
5413   /* Was the conflicted range the last range in the whole requested merge? */
5414   svn_boolean_t was_last_range;
5415 } conflict_report_t;
5416
5417 /* Return a new conflict_report_t containing deep copies of the parameters,
5418  * allocated in RESULT_POOL. */
5419 static conflict_report_t *
5420 conflict_report_create(const char *target_abspath,
5421                        const merge_source_t *conflicted_range,
5422                        svn_boolean_t was_last_range,
5423                        apr_pool_t *result_pool)
5424 {
5425   conflict_report_t *report = apr_palloc(result_pool, sizeof(*report));
5426
5427   report->target_abspath = apr_pstrdup(result_pool, target_abspath);
5428   report->conflicted_range = merge_source_dup(conflicted_range, result_pool);
5429   report->was_last_range = was_last_range;
5430   return report;
5431 }
5432
5433 /* Return a deep copy of REPORT, allocated in RESULT_POOL. */
5434 static conflict_report_t *
5435 conflict_report_dup(const conflict_report_t *report,
5436                     apr_pool_t *result_pool)
5437 {
5438   conflict_report_t *new = apr_pmemdup(result_pool, report, sizeof(*new));
5439
5440   new->target_abspath = apr_pstrdup(result_pool, report->target_abspath);
5441   new->conflicted_range = merge_source_dup(report->conflicted_range,
5442                                            result_pool);
5443   return new;
5444 }
5445
5446 /* Create and return an error structure appropriate for the unmerged
5447    revisions range(s). */
5448 static APR_INLINE svn_error_t *
5449 make_merge_conflict_error(conflict_report_t *report,
5450                           apr_pool_t *scratch_pool)
5451 {
5452   assert(!report || svn_dirent_is_absolute(report->target_abspath));
5453
5454   if (report && ! report->was_last_range)
5455     {
5456       svn_error_t *err = svn_error_createf(SVN_ERR_WC_FOUND_CONFLICT, NULL,
5457        _("One or more conflicts were produced while merging r%ld:%ld into\n"
5458          "'%s' --\n"
5459          "resolve all conflicts and rerun the merge to apply the remaining\n"
5460          "unmerged revisions"),
5461        report->conflicted_range->loc1->rev, report->conflicted_range->loc2->rev,
5462        svn_dirent_local_style(report->target_abspath, scratch_pool));
5463       assert(report->conflicted_range->loc1->rev != report->conflicted_range->loc2->rev); /* ### is a valid case in a 2-URL merge */
5464       return err;
5465     }
5466   return SVN_NO_ERROR;
5467 }
5468
5469 /* Helper for do_directory_merge().
5470
5471    TARGET_WCPATH is a directory and CHILDREN_WITH_MERGEINFO is filled
5472    with paths (svn_client__merge_path_t *) arranged in depth first order,
5473    which have mergeinfo set on them or meet one of the other criteria
5474    defined in get_mergeinfo_paths().  Remove any paths absent from disk
5475    or scheduled for deletion from CHILDREN_WITH_MERGEINFO which are equal to
5476    or are descendants of TARGET_WCPATH by setting those children to NULL. */
5477 static void
5478 remove_absent_children(const char *target_wcpath,
5479                        apr_array_header_t *children_with_mergeinfo)
5480 {
5481   /* Before we try to override mergeinfo for skipped paths, make sure
5482      the path isn't absent due to authz restrictions, because there's
5483      nothing we can do about those. */
5484   int i;
5485   for (i = 0; i < children_with_mergeinfo->nelts; i++)
5486     {
5487       svn_client__merge_path_t *child =
5488         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
5489       if ((child->absent || child->scheduled_for_deletion)
5490           && svn_dirent_is_ancestor(target_wcpath, child->abspath))
5491         {
5492           svn_sort__array_delete(children_with_mergeinfo, i--, 1);
5493         }
5494     }
5495 }
5496
5497 /* Helper for do_directory_merge() to handle the case where a merge editor
5498    drive removes explicit mergeinfo from a subtree of the merge target.
5499
5500    MERGE_B is cascaded from the argument of the same name in
5501    do_directory_merge().  For each path (if any) in
5502    MERGE_B->PATHS_WITH_DELETED_MERGEINFO remove that path from
5503    CHILDREN_WITH_MERGEINFO.
5504
5505    The one exception is for the merge target itself,
5506    MERGE_B->target->abspath, this must always be present in
5507    CHILDREN_WITH_MERGEINFO so this is never removed by this
5508    function. */
5509 static void
5510 remove_children_with_deleted_mergeinfo(merge_cmd_baton_t *merge_b,
5511                                        apr_array_header_t *children_with_mergeinfo)
5512 {
5513   int i;
5514
5515   if (!merge_b->paths_with_deleted_mergeinfo)
5516     return;
5517
5518   /* CHILDREN_WITH_MERGEINFO[0] is the always the merge target
5519      so start at the first child. */
5520   for (i = 1; i < children_with_mergeinfo->nelts; i++)
5521     {
5522       svn_client__merge_path_t *child =
5523         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
5524
5525       if (svn_hash_gets(merge_b->paths_with_deleted_mergeinfo, child->abspath))
5526         {
5527           svn_sort__array_delete(children_with_mergeinfo, i--, 1);
5528         }
5529     }
5530 }
5531
5532 /* Helper for do_directory_merge().
5533
5534    Set up the diff editor report to merge the SOURCE diff
5535    into TARGET_ABSPATH and drive it.
5536
5537    If mergeinfo is not being honored (based on MERGE_B -- see the doc
5538    string for HONOR_MERGEINFO() for how this is determined), then ignore
5539    CHILDREN_WITH_MERGEINFO and merge the SOURCE diff to TARGET_ABSPATH.
5540
5541    If mergeinfo is being honored then perform a history-aware merge,
5542    describing TARGET_ABSPATH and its subtrees to the reporter in such as way
5543    as to avoid repeating merges already performed per the mergeinfo and
5544    natural history of TARGET_ABSPATH and its subtrees.
5545
5546    The ranges that still need to be merged to the TARGET_ABSPATH and its
5547    subtrees are described in CHILDREN_WITH_MERGEINFO, an array of
5548    svn_client__merge_path_t * -- see 'THE CHILDREN_WITH_MERGEINFO ARRAY'
5549    comment at the top of this file for more info.  Note that it is possible
5550    TARGET_ABSPATH and/or some of its subtrees need only a subset, or no part,
5551    of SOURCE to be merged.  Though there is little point to
5552    calling this function if TARGET_ABSPATH and all its subtrees have already
5553    had SOURCE merged, this will work but is a no-op.
5554
5555    SOURCE->rev1 and SOURCE->rev2 must be bound by the set of remaining_ranges
5556    fields in CHILDREN_WITH_MERGEINFO's elements, specifically:
5557
5558    For forward merges (SOURCE->rev1 < SOURCE->rev2):
5559
5560      1) The first svn_merge_range_t * element of each child's remaining_ranges
5561         array must meet one of the following conditions:
5562
5563         a) The range's start field is greater than or equal to SOURCE->rev2.
5564
5565         b) The range's end field is SOURCE->rev2.
5566
5567      2) Among all the ranges that meet condition 'b' the oldest start
5568         revision must equal SOURCE->rev1.
5569
5570    For reverse merges (SOURCE->rev1 > SOURCE->rev2):
5571
5572      1) The first svn_merge_range_t * element of each child's remaining_ranges
5573         array must meet one of the following conditions:
5574
5575         a) The range's start field is less than or equal to SOURCE->rev2.
5576
5577         b) The range's end field is SOURCE->rev2.
5578
5579      2) Among all the ranges that meet condition 'b' the youngest start
5580         revision must equal SOURCE->rev1.
5581
5582    Note: If the first svn_merge_range_t * element of some subtree child's
5583    remaining_ranges array is the same as the first range of that child's
5584    nearest path-wise ancestor, then the subtree child *will not* be described
5585    to the reporter.
5586
5587    DEPTH, NOTIFY_B, and MERGE_B are cascaded from do_directory_merge(), see
5588    that function for more info.
5589
5590    MERGE_B->ra_session1 and MERGE_B->ra_session2 are RA sessions open to any
5591    URL in the repository of SOURCE; they may be temporarily reparented within
5592    this function.
5593
5594    If SOURCE->ancestral is set, then SOURCE->loc1 must be a
5595    historical ancestor of SOURCE->loc2, or vice-versa (see
5596    `MERGEINFO MERGE SOURCE NORMALIZATION' for more requirements around
5597    SOURCE in this case).
5598 */
5599 static svn_error_t *
5600 drive_merge_report_editor(const char *target_abspath,
5601                           const merge_source_t *source,
5602                           const apr_array_header_t *children_with_mergeinfo,
5603                           const svn_diff_tree_processor_t *processor,
5604                           svn_depth_t depth,
5605                           merge_cmd_baton_t *merge_b,
5606                           apr_pool_t *scratch_pool)
5607 {
5608   const svn_ra_reporter3_t *reporter;
5609   const svn_delta_editor_t *diff_editor;
5610   void *diff_edit_baton;
5611   void *report_baton;
5612   svn_revnum_t target_start;
5613   svn_boolean_t honor_mergeinfo = HONOR_MERGEINFO(merge_b);
5614   const char *old_sess1_url, *old_sess2_url;
5615   svn_boolean_t is_rollback = source->loc1->rev > source->loc2->rev;
5616
5617   /* Start with a safe default starting revision for the editor and the
5618      merge target. */
5619   target_start = source->loc1->rev;
5620
5621   /* If we are honoring mergeinfo the starting revision for the merge target
5622      might not be SOURCE->rev1, in fact the merge target might not need *any*
5623      part of SOURCE merged -- Instead some subtree of the target
5624      needs SOURCE -- So get the right starting revision for the
5625      target. */
5626   if (honor_mergeinfo)
5627     {
5628       svn_client__merge_path_t *child;
5629
5630       /* CHILDREN_WITH_MERGEINFO must always exist if we are honoring
5631          mergeinfo and must have at least one element (describing the
5632          merge target). */
5633       SVN_ERR_ASSERT(children_with_mergeinfo);
5634       SVN_ERR_ASSERT(children_with_mergeinfo->nelts);
5635
5636       /* Get the merge target's svn_client__merge_path_t, which is always
5637          the first in the array due to depth first sorting requirement,
5638          see 'THE CHILDREN_WITH_MERGEINFO ARRAY'. */
5639       child = APR_ARRAY_IDX(children_with_mergeinfo, 0,
5640                             svn_client__merge_path_t *);
5641       SVN_ERR_ASSERT(child);
5642       if (child->remaining_ranges->nelts == 0)
5643         {
5644           /* The merge target doesn't need anything merged. */
5645           target_start = source->loc2->rev;
5646         }
5647       else
5648         {
5649           /* The merge target has remaining revisions to merge.  These
5650              ranges may fully or partially overlap the range described
5651              by SOURCE->rev1:rev2 or may not intersect that range at
5652              all. */
5653           svn_merge_range_t *range =
5654             APR_ARRAY_IDX(child->remaining_ranges, 0,
5655                           svn_merge_range_t *);
5656           if ((!is_rollback && range->start > source->loc2->rev)
5657               || (is_rollback && range->start < source->loc2->rev))
5658             {
5659               /* Merge target's first remaining range doesn't intersect. */
5660               target_start = source->loc2->rev;
5661             }
5662           else
5663             {
5664               /* Merge target's first remaining range partially or
5665                  fully overlaps. */
5666               target_start = range->start;
5667             }
5668         }
5669     }
5670
5671   SVN_ERR(svn_client__ensure_ra_session_url(&old_sess1_url,
5672                                             merge_b->ra_session1,
5673                                             source->loc1->url, scratch_pool));
5674   /* Temporarily point our second RA session to SOURCE->loc1->url, too.  We use
5675      this to request individual file contents. */
5676   SVN_ERR(svn_client__ensure_ra_session_url(&old_sess2_url,
5677                                             merge_b->ra_session2,
5678                                             source->loc1->url, scratch_pool));
5679
5680   /* Get the diff editor and a reporter with which to, ultimately,
5681      drive it. */
5682   SVN_ERR(svn_client__get_diff_editor2(&diff_editor, &diff_edit_baton,
5683                                        merge_b->ra_session2,
5684                                        depth,
5685                                        source->loc1->rev,
5686                                        TRUE /* text_deltas */,
5687                                        processor,
5688                                        merge_b->ctx->cancel_func,
5689                                        merge_b->ctx->cancel_baton,
5690                                        scratch_pool));
5691   SVN_ERR(svn_ra_do_diff3(merge_b->ra_session1,
5692                           &reporter, &report_baton, source->loc2->rev,
5693                           "", depth, merge_b->diff_ignore_ancestry,
5694                           TRUE,  /* text_deltas */
5695                           source->loc2->url, diff_editor, diff_edit_baton,
5696                           scratch_pool));
5697
5698   /* Drive the reporter. */
5699   SVN_ERR(reporter->set_path(report_baton, "", target_start, depth,
5700                              FALSE, NULL, scratch_pool));
5701   if (honor_mergeinfo && children_with_mergeinfo)
5702     {
5703       /* Describe children with mergeinfo overlapping this merge
5704          operation such that no repeated diff is retrieved for them from
5705          the repository. */
5706       int i;
5707       apr_pool_t *iterpool = svn_pool_create(scratch_pool);
5708
5709       /* Start with CHILDREN_WITH_MERGEINFO[1], CHILDREN_WITH_MERGEINFO[0]
5710          is always the merge target (TARGET_ABSPATH). */
5711       for (i = 1; i < children_with_mergeinfo->nelts; i++)
5712         {
5713           svn_merge_range_t *range;
5714           const char *child_repos_path;
5715           const svn_client__merge_path_t *parent;
5716           const svn_client__merge_path_t *child =
5717             APR_ARRAY_IDX(children_with_mergeinfo, i,
5718                           svn_client__merge_path_t *);
5719
5720           SVN_ERR_ASSERT(child);
5721           if (child->absent)
5722             continue;
5723
5724           svn_pool_clear(iterpool);
5725
5726           /* Find this child's nearest wc ancestor with mergeinfo. */
5727           parent = find_nearest_ancestor(children_with_mergeinfo,
5728                                          FALSE, child->abspath);
5729
5730           /* If a subtree needs the same range applied as its nearest parent
5731              with mergeinfo or neither the subtree nor this parent need
5732              SOURCE->rev1:rev2 merged, then we don't need to describe the
5733              subtree separately.  In the latter case this could break the
5734              editor if child->abspath didn't exist at SOURCE->rev2 and we
5735              attempt to describe it via a reporter set_path call. */
5736           if (child->remaining_ranges->nelts)
5737             {
5738               range = APR_ARRAY_IDX(child->remaining_ranges, 0,
5739                                     svn_merge_range_t *);
5740               if ((!is_rollback && range->start > source->loc2->rev)
5741                   || (is_rollback && range->start < source->loc2->rev))
5742                 {
5743                   /* This child's first remaining range comes after the range
5744                      we are currently merging, so skip it. We expect to get
5745                      to it in a subsequent call to this function. */
5746                   continue;
5747                 }
5748               else if (parent->remaining_ranges->nelts)
5749                 {
5750                    svn_merge_range_t *parent_range =
5751                     APR_ARRAY_IDX(parent->remaining_ranges, 0,
5752                                   svn_merge_range_t *);
5753                    svn_merge_range_t *child_range =
5754                     APR_ARRAY_IDX(child->remaining_ranges, 0,
5755                                   svn_merge_range_t *);
5756                   if (parent_range->start == child_range->start)
5757                     continue; /* Subtree needs same range as parent. */
5758                 }
5759             }
5760           else /* child->remaining_ranges->nelts == 0*/
5761             {
5762               /* If both the subtree and its parent need no ranges applied
5763                  consider that as the "same ranges" and don't describe
5764                  the subtree. */
5765               if (parent->remaining_ranges->nelts == 0)
5766                 continue;
5767             }
5768
5769           /* Ok, we really need to describe this subtree as it needs different
5770              ranges applied than its nearest working copy parent. */
5771           child_repos_path = svn_dirent_is_child(target_abspath,
5772                                                  child->abspath,
5773                                                  iterpool);
5774           /* This loop is only processing subtrees, so CHILD->ABSPATH
5775              better be a proper child of the merge target. */
5776           SVN_ERR_ASSERT(child_repos_path);
5777
5778           if ((child->remaining_ranges->nelts == 0)
5779               || (is_rollback && (range->start < source->loc2->rev))
5780               || (!is_rollback && (range->start > source->loc2->rev)))
5781             {
5782               /* Nothing to merge to this child.  We'll claim we have
5783                  it up to date so the server doesn't send us
5784                  anything. */
5785               SVN_ERR(reporter->set_path(report_baton, child_repos_path,
5786                                          source->loc2->rev, depth, FALSE,
5787                                          NULL, iterpool));
5788             }
5789           else
5790             {
5791               SVN_ERR(reporter->set_path(report_baton, child_repos_path,
5792                                          range->start, depth, FALSE,
5793                                          NULL, iterpool));
5794             }
5795         }
5796       svn_pool_destroy(iterpool);
5797     }
5798   SVN_ERR(reporter->finish_report(report_baton, scratch_pool));
5799
5800   /* Point the merge baton's RA sessions back where they were. */
5801   SVN_ERR(svn_ra_reparent(merge_b->ra_session1, old_sess1_url, scratch_pool));
5802   SVN_ERR(svn_ra_reparent(merge_b->ra_session2, old_sess2_url, scratch_pool));
5803
5804   return SVN_NO_ERROR;
5805 }
5806
5807 /* Iterate over each svn_client__merge_path_t * element in
5808    CHILDREN_WITH_MERGEINFO and, if START_REV is true, find the most inclusive
5809    start revision among those element's first remaining_ranges element.  If
5810    START_REV is false, then look for the most inclusive end revision.
5811
5812    If IS_ROLLBACK is true the youngest start or end (as per START_REV)
5813    revision is considered the "most inclusive" otherwise the oldest revision
5814    is.
5815
5816    If none of CHILDREN_WITH_MERGEINFO's elements have any remaining ranges
5817    return SVN_INVALID_REVNUM. */
5818 static svn_revnum_t
5819 get_most_inclusive_rev(const apr_array_header_t *children_with_mergeinfo,
5820                        svn_boolean_t is_rollback,
5821                        svn_boolean_t start_rev)
5822 {
5823   int i;
5824   svn_revnum_t most_inclusive_rev = SVN_INVALID_REVNUM;
5825
5826   for (i = 0; i < children_with_mergeinfo->nelts; i++)
5827     {
5828       svn_client__merge_path_t *child =
5829         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
5830
5831       if ((! child) || child->absent)
5832         continue;
5833       if (child->remaining_ranges->nelts > 0)
5834         {
5835           svn_merge_range_t *range =
5836             APR_ARRAY_IDX(child->remaining_ranges, 0, svn_merge_range_t *);
5837
5838           /* Are we looking for the most inclusive start or end rev? */
5839           svn_revnum_t rev = start_rev ? range->start : range->end;
5840
5841           if ((most_inclusive_rev == SVN_INVALID_REVNUM)
5842               || (is_rollback && (rev > most_inclusive_rev))
5843               || ((! is_rollback) && (rev < most_inclusive_rev)))
5844             most_inclusive_rev = rev;
5845         }
5846     }
5847   return most_inclusive_rev;
5848 }
5849
5850
5851 /* If first item in each child of CHILDREN_WITH_MERGEINFO's
5852    remaining_ranges is inclusive of END_REV, Slice the first range in
5853    to two at END_REV. All the allocations are persistent and allocated
5854    from POOL. */
5855 static void
5856 slice_remaining_ranges(apr_array_header_t *children_with_mergeinfo,
5857                        svn_boolean_t is_rollback, svn_revnum_t end_rev,
5858                        apr_pool_t *pool)
5859 {
5860   int i;
5861   for (i = 0; i < children_with_mergeinfo->nelts; i++)
5862     {
5863       svn_client__merge_path_t *child =
5864                                      APR_ARRAY_IDX(children_with_mergeinfo, i,
5865                                                    svn_client__merge_path_t *);
5866       if (!child || child->absent)
5867         continue;
5868       if (child->remaining_ranges->nelts > 0)
5869         {
5870           svn_merge_range_t *range = APR_ARRAY_IDX(child->remaining_ranges, 0,
5871                                                    svn_merge_range_t *);
5872           if ((is_rollback && (range->start > end_rev)
5873                && (range->end < end_rev))
5874               || (!is_rollback && (range->start < end_rev)
5875                   && (range->end > end_rev)))
5876             {
5877               svn_merge_range_t *split_range1, *split_range2;
5878
5879               split_range1 = svn_merge_range_dup(range, pool);
5880               split_range2 = svn_merge_range_dup(range, pool);
5881               split_range1->end = end_rev;
5882               split_range2->start = end_rev;
5883               APR_ARRAY_IDX(child->remaining_ranges, 0,
5884                             svn_merge_range_t *) = split_range1;
5885               svn_sort__array_insert(&split_range2, child->remaining_ranges, 1);
5886             }
5887         }
5888     }
5889 }
5890
5891 /* Helper for do_directory_merge().
5892
5893    For each child in CHILDREN_WITH_MERGEINFO remove the first remaining_ranges
5894    svn_merge_range_t *element of the child if that range has an end revision
5895    equal to REVISION.
5896
5897    If a range is removed from a child's remaining_ranges array, allocate the
5898    new remaining_ranges array in POOL.
5899  */
5900 static void
5901 remove_first_range_from_remaining_ranges(svn_revnum_t revision,
5902                                          apr_array_header_t
5903                                            *children_with_mergeinfo,
5904                                          apr_pool_t *pool)
5905 {
5906   int i;
5907
5908   for (i = 0; i < children_with_mergeinfo->nelts; i++)
5909     {
5910       svn_client__merge_path_t *child =
5911                                 APR_ARRAY_IDX(children_with_mergeinfo, i,
5912                                               svn_client__merge_path_t *);
5913       if (!child || child->absent)
5914         continue;
5915       if (child->remaining_ranges->nelts > 0)
5916         {
5917           svn_merge_range_t *first_range =
5918             APR_ARRAY_IDX(child->remaining_ranges, 0, svn_merge_range_t *);
5919           if (first_range->end == revision)
5920             {
5921               svn_sort__array_delete(child->remaining_ranges, 0, 1);
5922             }
5923         }
5924     }
5925 }
5926
5927 /* Get a file's content and properties from the repository.
5928    Set *FILENAME to the local path to a new temporary file holding its text,
5929    and set *PROPS to a new hash of its properties.
5930
5931    RA_SESSION is a session open to the correct repository, which will be
5932    temporarily reparented to the URL of the file itself.  LOCATION is the
5933    repository location of the file.
5934
5935    The resulting file and the return values live as long as RESULT_POOL, all
5936    other allocations occur in SCRATCH_POOL.
5937 */
5938 static svn_error_t *
5939 single_file_merge_get_file(const char **filename,
5940                            apr_hash_t **props,
5941                            svn_ra_session_t *ra_session,
5942                            const svn_client__pathrev_t *location,
5943                            const char *wc_target,
5944                            apr_pool_t *result_pool,
5945                            apr_pool_t *scratch_pool)
5946 {
5947   svn_stream_t *stream;
5948   const char *old_sess_url;
5949   svn_error_t *err;
5950
5951   SVN_ERR(svn_stream_open_unique(&stream, filename, NULL,
5952                                  svn_io_file_del_on_pool_cleanup,
5953                                  result_pool, scratch_pool));
5954
5955   SVN_ERR(svn_client__ensure_ra_session_url(&old_sess_url, ra_session, location->url,
5956                                             scratch_pool));
5957   err = svn_ra_get_file(ra_session, "", location->rev,
5958                         stream, NULL, props, scratch_pool);
5959   SVN_ERR(svn_error_compose_create(
5960             err, svn_ra_reparent(ra_session, old_sess_url, scratch_pool)));
5961
5962   return svn_error_trace(svn_stream_close(stream));
5963 }
5964
5965 /* Compare two svn_client__merge_path_t elements **A and **B, given the
5966    addresses of pointers to them. Return an integer less than, equal to, or
5967    greater than zero if A sorts before, the same as, or after B, respectively.
5968    This is a helper for qsort() and bsearch() on an array of such elements. */
5969 static int
5970 compare_merge_path_t_as_paths(const void *a,
5971                               const void *b)
5972 {
5973   const svn_client__merge_path_t *child1
5974     = *((const svn_client__merge_path_t * const *) a);
5975   const svn_client__merge_path_t *child2
5976     = *((const svn_client__merge_path_t * const *) b);
5977
5978   return svn_path_compare_paths(child1->abspath, child2->abspath);
5979 }
5980
5981 /* Return a pointer to the element of CHILDREN_WITH_MERGEINFO whose path
5982  * is PATH, or return NULL if there is no such element. */
5983 static svn_client__merge_path_t *
5984 get_child_with_mergeinfo(const apr_array_header_t *children_with_mergeinfo,
5985                          const char *abspath)
5986 {
5987   svn_client__merge_path_t merge_path;
5988   svn_client__merge_path_t *key;
5989   svn_client__merge_path_t **pchild;
5990
5991   merge_path.abspath = abspath;
5992   key = &merge_path;
5993   pchild = bsearch(&key, children_with_mergeinfo->elts,
5994                    children_with_mergeinfo->nelts,
5995                    children_with_mergeinfo->elt_size,
5996                    compare_merge_path_t_as_paths);
5997   return pchild ? *pchild : NULL;
5998 }
5999
6000 /* Insert a deep copy of INSERT_ELEMENT into the CHILDREN_WITH_MERGEINFO
6001    array at its correct position.  Allocate the new storage in POOL.
6002    CHILDREN_WITH_MERGEINFO is a depth first sorted array of
6003    (svn_client__merge_path_t *).
6004
6005    ### Most callers don't need this to deep-copy the new element.
6006    ### It may be more efficient for some callers to insert a bunch of items
6007        out of order and then sort afterwards. (One caller is doing a qsort
6008        after calling this anyway.)
6009  */
6010 static void
6011 insert_child_to_merge(apr_array_header_t *children_with_mergeinfo,
6012                       const svn_client__merge_path_t *insert_element,
6013                       apr_pool_t *pool)
6014 {
6015   int insert_index;
6016   const svn_client__merge_path_t *new_element;
6017
6018   /* Find where to insert the new element */
6019   insert_index =
6020     svn_sort__bsearch_lower_bound(&insert_element, children_with_mergeinfo,
6021                                   compare_merge_path_t_as_paths);
6022
6023   new_element = svn_client__merge_path_dup(insert_element, pool);
6024   svn_sort__array_insert(&new_element, children_with_mergeinfo, insert_index);
6025 }
6026
6027 /* Helper for get_mergeinfo_paths().
6028
6029    CHILDREN_WITH_MERGEINFO, DEPTH, and POOL are
6030    all cascaded from the arguments of the same name to get_mergeinfo_paths().
6031
6032    TARGET is the merge target.
6033
6034    *CHILD is the element in in CHILDREN_WITH_MERGEINFO that
6035    get_mergeinfo_paths() is iterating over and *CURR_INDEX is index for
6036    *CHILD.
6037
6038    If CHILD->ABSPATH is equal to MERGE_CMD_BATON->target->abspath do nothing.
6039    Else if CHILD->ABSPATH is switched or absent then make sure its immediate
6040    (as opposed to nearest) parent in CHILDREN_WITH_MERGEINFO is marked as
6041    missing a child.  If the immediate parent does not exist in
6042    CHILDREN_WITH_MERGEINFO then create it (and increment *CURR_INDEX so that
6043    caller doesn't process the inserted element).  Also ensure that
6044    CHILD->ABSPATH's siblings which are not already present in
6045    CHILDREN_WITH_MERGEINFO are also added to the array, limited by DEPTH
6046    (e.g. don't add directory siblings of a switched file).
6047    Use POOL for temporary allocations only, any new CHILDREN_WITH_MERGEINFO
6048    elements are allocated in POOL. */
6049 static svn_error_t *
6050 insert_parent_and_sibs_of_sw_absent_del_subtree(
6051                                    apr_array_header_t *children_with_mergeinfo,
6052                                    const merge_target_t *target,
6053                                    int *curr_index,
6054                                    svn_client__merge_path_t *child,
6055                                    svn_depth_t depth,
6056                                    svn_client_ctx_t *ctx,
6057                                    apr_pool_t *pool)
6058 {
6059   svn_client__merge_path_t *parent;
6060   const char *parent_abspath;
6061   apr_pool_t *iterpool;
6062   const apr_array_header_t *children;
6063   int i;
6064
6065   if (!(child->absent
6066           || (child->switched
6067               && strcmp(target->abspath,
6068                         child->abspath) != 0)))
6069     return SVN_NO_ERROR;
6070
6071   parent_abspath = svn_dirent_dirname(child->abspath, pool);
6072   parent = get_child_with_mergeinfo(children_with_mergeinfo, parent_abspath);
6073   if (parent)
6074     {
6075       parent->missing_child = child->absent;
6076       parent->switched_child = child->switched;
6077     }
6078   else
6079     {
6080       /* Create a new element to insert into CHILDREN_WITH_MERGEINFO. */
6081       parent = svn_client__merge_path_create(parent_abspath, pool);
6082       parent->missing_child = child->absent;
6083       parent->switched_child = child->switched;
6084       /* Insert PARENT into CHILDREN_WITH_MERGEINFO. */
6085       insert_child_to_merge(children_with_mergeinfo, parent, pool);
6086       /* Increment for loop index so we don't process the inserted element. */
6087       (*curr_index)++;
6088     } /*(parent == NULL) */
6089
6090   /* Add all of PARENT's non-missing children that are not already present.*/
6091   SVN_ERR(svn_wc__node_get_children(&children, ctx->wc_ctx,
6092                                     parent_abspath, FALSE, pool, pool));
6093   iterpool = svn_pool_create(pool);
6094   for (i = 0; i < children->nelts; i++)
6095     {
6096       const char *child_abspath = APR_ARRAY_IDX(children, i, const char *);
6097       svn_client__merge_path_t *sibling_of_missing;
6098
6099       svn_pool_clear(iterpool);
6100
6101       /* Does this child already exist in CHILDREN_WITH_MERGEINFO? */
6102       sibling_of_missing = get_child_with_mergeinfo(children_with_mergeinfo,
6103                                                     child_abspath);
6104       /* Create the missing child and insert it into CHILDREN_WITH_MERGEINFO.*/
6105       if (!sibling_of_missing)
6106         {
6107           /* Don't add directory children if DEPTH is svn_depth_files. */
6108           if (depth == svn_depth_files)
6109             {
6110               svn_node_kind_t child_kind;
6111
6112               SVN_ERR(svn_wc_read_kind2(&child_kind,
6113                                         ctx->wc_ctx, child_abspath,
6114                                         FALSE, FALSE, iterpool));
6115               if (child_kind != svn_node_file)
6116                 continue;
6117             }
6118
6119           sibling_of_missing = svn_client__merge_path_create(child_abspath,
6120                                                              pool);
6121           insert_child_to_merge(children_with_mergeinfo, sibling_of_missing,
6122                                 pool);
6123         }
6124     }
6125
6126   svn_pool_destroy(iterpool);
6127
6128   return SVN_NO_ERROR;
6129 }
6130
6131 /* pre_merge_status_cb's baton */
6132 struct pre_merge_status_baton_t
6133 {
6134   svn_wc_context_t *wc_ctx;
6135
6136   /* const char *absolute_wc_path to svn_depth_t * mapping for depths
6137      of empty, immediates, and files. */
6138   apr_hash_t *shallow_subtrees;
6139
6140   /* const char *absolute_wc_path to the same, for all paths missing
6141      from the working copy. */
6142   apr_hash_t *missing_subtrees;
6143
6144   /* const char *absolute_wc_path const char * repos relative path, describing
6145      the root of each switched subtree in the working copy and the repository
6146      relative path it is switched to. */
6147   apr_hash_t *switched_subtrees;
6148
6149   /* A pool to allocate additions to the above hashes in. */
6150   apr_pool_t *pool;
6151 };
6152
6153 /* A svn_wc_status_func4_t callback used by get_mergeinfo_paths to gather
6154    all switched, depth filtered and missing subtrees under a merge target.
6155
6156    Note that this doesn't see server and user excluded trees. */
6157 static svn_error_t *
6158 pre_merge_status_cb(void *baton,
6159                     const char *local_abspath,
6160                     const svn_wc_status3_t *status,
6161                     apr_pool_t *scratch_pool)
6162 {
6163   struct pre_merge_status_baton_t *pmsb = baton;
6164
6165   if (status->switched && !status->file_external)
6166     {
6167       store_path(pmsb->switched_subtrees, local_abspath);
6168     }
6169
6170   if (status->depth == svn_depth_empty
6171       || status->depth == svn_depth_files)
6172     {
6173       const char *dup_abspath;
6174       svn_depth_t *depth = apr_pmemdup(pmsb->pool, &status->depth,
6175                                        sizeof *depth);
6176
6177       dup_abspath = apr_pstrdup(pmsb->pool, local_abspath);
6178
6179       svn_hash_sets(pmsb->shallow_subtrees, dup_abspath, depth);
6180     }
6181
6182   if (status->node_status == svn_wc_status_missing)
6183     {
6184       svn_boolean_t new_missing_root = TRUE;
6185       apr_hash_index_t *hi;
6186
6187       for (hi = apr_hash_first(scratch_pool, pmsb->missing_subtrees);
6188            hi;
6189            hi = apr_hash_next(hi))
6190         {
6191           const char *missing_root_path = svn__apr_hash_index_key(hi);
6192
6193           if (svn_dirent_is_ancestor(missing_root_path,
6194                                      local_abspath))
6195             {
6196               new_missing_root = FALSE;
6197               break;
6198             }
6199         }
6200
6201       if (new_missing_root)
6202         store_path(pmsb->missing_subtrees, local_abspath);
6203     }
6204
6205   return SVN_NO_ERROR;
6206 }
6207
6208 /* Find all the subtrees in the working copy tree rooted at TARGET_ABSPATH
6209  * that have explicit mergeinfo.
6210  * Set *SUBTREES_WITH_MERGEINFO to a hash mapping (const char *) absolute
6211  * WC path to (svn_mergeinfo_t *) mergeinfo.
6212  *
6213  * ### Is this function equivalent to:
6214  *
6215  *   svn_client__get_wc_mergeinfo_catalog(
6216  *     subtrees_with_mergeinfo, inherited=NULL, include_descendants=TRUE,
6217  *     svn_mergeinfo_explicit, target_abspath, limit_path=NULL,
6218  *     walked_path=NULL, ignore_invalid_mergeinfo=FALSE, ...)
6219  *
6220  *   except for the catalog keys being abspaths instead of repo-relpaths?
6221  */
6222 static svn_error_t *
6223 get_wc_explicit_mergeinfo_catalog(apr_hash_t **subtrees_with_mergeinfo,
6224                                   const char *target_abspath,
6225                                   svn_depth_t depth,
6226                                   svn_client_ctx_t *ctx,
6227                                   apr_pool_t *result_pool,
6228                                   apr_pool_t *scratch_pool)
6229 {
6230   svn_opt_revision_t working_revision = { svn_opt_revision_working, { 0 } };
6231   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
6232   apr_hash_index_t *hi;
6233   apr_hash_t *externals;
6234
6235   SVN_ERR(svn_client_propget5(subtrees_with_mergeinfo, NULL,
6236                               SVN_PROP_MERGEINFO, target_abspath,
6237                               &working_revision, &working_revision, NULL,
6238                               depth, NULL, ctx, result_pool, scratch_pool));
6239
6240   SVN_ERR(svn_wc__externals_defined_below(&externals, ctx->wc_ctx,
6241                                           target_abspath, scratch_pool,
6242                                           scratch_pool));
6243
6244   /* Convert property values to svn_mergeinfo_t. */
6245   for (hi = apr_hash_first(scratch_pool, *subtrees_with_mergeinfo);
6246        hi;
6247        hi = apr_hash_next(hi))
6248     {
6249       const char *wc_path = svn__apr_hash_index_key(hi);
6250       svn_string_t *mergeinfo_string = svn__apr_hash_index_val(hi);
6251       svn_mergeinfo_t mergeinfo;
6252       svn_error_t *err;
6253
6254       /* svn_client_propget5 picks up file externals with
6255          mergeinfo, but we don't want those. */
6256       if (svn_hash_gets(externals, wc_path))
6257         {
6258           svn_hash_sets(*subtrees_with_mergeinfo, wc_path, NULL);
6259           continue;
6260         }
6261
6262       svn_pool_clear(iterpool);
6263
6264       err = svn_mergeinfo_parse(&mergeinfo, mergeinfo_string->data,
6265                                 result_pool);
6266       if (err)
6267         {
6268           if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
6269             {
6270               err = svn_error_createf(
6271                 SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING, err,
6272                 _("Invalid mergeinfo detected on '%s', "
6273                   "merge tracking not possible"),
6274                 svn_dirent_local_style(wc_path, scratch_pool));
6275             }
6276           return svn_error_trace(err);
6277         }
6278       svn_hash_sets(*subtrees_with_mergeinfo, wc_path, mergeinfo);
6279     }
6280   svn_pool_destroy(iterpool);
6281
6282   return SVN_NO_ERROR;
6283 }
6284
6285 /* Helper for do_directory_merge() when performing merge-tracking aware
6286    merges.
6287
6288    Walk of the working copy tree rooted at TARGET->abspath to
6289    depth DEPTH.  Create an svn_client__merge_path_t * for any path which meets
6290    one or more of the following criteria:
6291
6292      1) Path has working svn:mergeinfo.
6293      2) Path is switched.
6294      3) Path is a subtree of the merge target (i.e. is not equal to
6295         TARGET->abspath) and has no mergeinfo of its own but
6296         its immediate parent has mergeinfo with non-inheritable ranges.  If
6297         this isn't a dry-run and the merge is between differences in the same
6298         repository, then this function will set working mergeinfo on the path
6299         equal to the mergeinfo inheritable from its parent.
6300      4) Path has an immediate child (or children) missing from the WC because
6301         the child is switched or absent from the WC, or due to a sparse
6302         checkout.
6303      5) Path has a sibling (or siblings) missing from the WC because the
6304         sibling is switched, absent, scheduled for deletion, or missing due to
6305         a sparse checkout.
6306      6) Path is absent from disk due to an authz restriction.
6307      7) Path is equal to TARGET->abspath.
6308      8) Path is an immediate *directory* child of
6309         TARGET->abspath and DEPTH is svn_depth_immediates.
6310      9) Path is an immediate *file* child of TARGET->abspath
6311         and DEPTH is svn_depth_files.
6312      10) Path is at a depth of 'empty' or 'files'.
6313      11) Path is missing from disk (e.g. due to an OS-level deletion).
6314
6315    If subtrees within the requested DEPTH are unexpectedly missing disk,
6316    then raise SVN_ERR_CLIENT_NOT_READY_TO_MERGE.
6317
6318    Store the svn_client__merge_path_t *'s in *CHILDREN_WITH_MERGEINFO in
6319    depth-first order based on the svn_client__merge_path_t *s path member as
6320    sorted by svn_path_compare_paths().  Set the remaining_ranges field of each
6321    element to NULL.
6322
6323    Note: Since the walk is rooted at TARGET->abspath, the
6324    latter is guaranteed to be in *CHILDREN_WITH_MERGEINFO and due to the
6325    depth-first ordering it is guaranteed to be the first element in
6326    *CHILDREN_WITH_MERGEINFO.
6327
6328    MERGE_CMD_BATON is cascaded from the argument of the same name in
6329    do_directory_merge().
6330 */
6331 static svn_error_t *
6332 get_mergeinfo_paths(apr_array_header_t *children_with_mergeinfo,
6333                     const merge_target_t *target,
6334                     svn_depth_t depth,
6335                     svn_boolean_t dry_run,
6336                     svn_boolean_t same_repos,
6337                     svn_client_ctx_t *ctx,
6338                     apr_pool_t *result_pool,
6339                     apr_pool_t *scratch_pool)
6340 {
6341   int i;
6342   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
6343   apr_hash_t *subtrees_with_mergeinfo;
6344   apr_hash_t *excluded_subtrees;
6345   apr_hash_t *switched_subtrees;
6346   apr_hash_t *shallow_subtrees;
6347   apr_hash_t *missing_subtrees;
6348   struct pre_merge_status_baton_t pre_merge_status_baton;
6349
6350   /* Case 1: Subtrees with explicit mergeinfo. */
6351   SVN_ERR(get_wc_explicit_mergeinfo_catalog(&subtrees_with_mergeinfo,
6352                                             target->abspath,
6353                                             depth, ctx,
6354                                             result_pool, scratch_pool));
6355   if (subtrees_with_mergeinfo)
6356     {
6357       apr_hash_index_t *hi;
6358
6359       for (hi = apr_hash_first(scratch_pool, subtrees_with_mergeinfo);
6360            hi;
6361            hi = apr_hash_next(hi))
6362         {
6363           const char *wc_path = svn__apr_hash_index_key(hi);
6364           svn_mergeinfo_t mergeinfo = svn__apr_hash_index_val(hi);
6365           svn_client__merge_path_t *mergeinfo_child =
6366             svn_client__merge_path_create(wc_path, result_pool);
6367
6368           svn_pool_clear(iterpool);
6369
6370           /* Stash this child's pre-existing mergeinfo. */
6371           mergeinfo_child->pre_merge_mergeinfo = mergeinfo;
6372
6373           /* Note if this child has non-inheritable mergeinfo */
6374           mergeinfo_child->has_noninheritable
6375             = svn_mergeinfo__is_noninheritable(
6376                 mergeinfo_child->pre_merge_mergeinfo, iterpool);
6377
6378           /* Append it.  We'll sort below. */
6379           APR_ARRAY_PUSH(children_with_mergeinfo, svn_client__merge_path_t *)
6380             = svn_client__merge_path_dup(mergeinfo_child, result_pool);
6381         }
6382
6383       /* Sort CHILDREN_WITH_MERGEINFO by each child's path (i.e. as per
6384          compare_merge_path_t_as_paths).  Any subsequent insertions of new
6385          children with insert_child_to_merge() require this ordering. */
6386       qsort(children_with_mergeinfo->elts,
6387             children_with_mergeinfo->nelts,
6388             children_with_mergeinfo->elt_size,
6389             compare_merge_path_t_as_paths);
6390     }
6391
6392   /* Case 2: Switched subtrees
6393      Case 10: Paths at depths of 'empty' or 'files'
6394      Case 11: Paths missing from disk */
6395   pre_merge_status_baton.wc_ctx = ctx->wc_ctx;
6396   switched_subtrees = apr_hash_make(scratch_pool);
6397   pre_merge_status_baton.switched_subtrees = switched_subtrees;
6398   shallow_subtrees = apr_hash_make(scratch_pool);
6399   pre_merge_status_baton.shallow_subtrees = shallow_subtrees;
6400   missing_subtrees = apr_hash_make(scratch_pool);
6401   pre_merge_status_baton.missing_subtrees = missing_subtrees;
6402   pre_merge_status_baton.pool = scratch_pool;
6403   SVN_ERR(svn_wc_walk_status(ctx->wc_ctx,
6404                              target->abspath,
6405                              depth,
6406                              TRUE /* get_all */,
6407                              FALSE /* no_ignore */,
6408                              TRUE /* ignore_text_mods */,
6409                              NULL /* ingore_patterns */,
6410                              pre_merge_status_cb, &pre_merge_status_baton,
6411                              ctx->cancel_func, ctx->cancel_baton,
6412                              scratch_pool));
6413
6414   /* Issue #2915: Raise an error describing the roots of any missing
6415      subtrees, i.e. those that the WC thinks are on disk but have been
6416      removed outside of Subversion. */
6417   if (apr_hash_count(missing_subtrees))
6418     {
6419       apr_hash_index_t *hi;
6420       svn_stringbuf_t *missing_subtree_err_buf =
6421         svn_stringbuf_create(_("Merge tracking not allowed with missing "
6422                                "subtrees; try restoring these items "
6423                                "first:\n"), scratch_pool);
6424
6425       for (hi = apr_hash_first(scratch_pool, missing_subtrees);
6426            hi;
6427            hi = apr_hash_next(hi))
6428         {
6429           svn_pool_clear(iterpool);
6430           svn_stringbuf_appendcstr(missing_subtree_err_buf,
6431                                    svn_dirent_local_style(
6432                                      svn__apr_hash_index_key(hi), iterpool));
6433           svn_stringbuf_appendcstr(missing_subtree_err_buf, "\n");
6434         }
6435
6436       return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE,
6437                               NULL, missing_subtree_err_buf->data);
6438     }
6439
6440   if (apr_hash_count(switched_subtrees))
6441     {
6442       apr_hash_index_t *hi;
6443
6444       for (hi = apr_hash_first(scratch_pool, switched_subtrees);
6445            hi;
6446            hi = apr_hash_next(hi))
6447         {
6448            const char *wc_path = svn__apr_hash_index_key(hi);
6449            svn_client__merge_path_t *child = get_child_with_mergeinfo(
6450              children_with_mergeinfo, wc_path);
6451
6452            if (child)
6453              {
6454                child->switched = TRUE;
6455              }
6456            else
6457              {
6458                svn_client__merge_path_t *switched_child =
6459                  svn_client__merge_path_create(wc_path, result_pool);
6460                switched_child->switched = TRUE;
6461                insert_child_to_merge(children_with_mergeinfo, switched_child,
6462                                      result_pool);
6463              }
6464         }
6465     }
6466
6467   if (apr_hash_count(shallow_subtrees))
6468     {
6469       apr_hash_index_t *hi;
6470
6471       for (hi = apr_hash_first(scratch_pool, shallow_subtrees);
6472            hi;
6473            hi = apr_hash_next(hi))
6474         {
6475            svn_boolean_t new_shallow_child = FALSE;
6476            const char *wc_path = svn__apr_hash_index_key(hi);
6477            svn_depth_t *child_depth = svn__apr_hash_index_val(hi);
6478            svn_client__merge_path_t *shallow_child = get_child_with_mergeinfo(
6479              children_with_mergeinfo, wc_path);
6480
6481            if (shallow_child)
6482              {
6483                if (*child_depth == svn_depth_empty
6484                    || *child_depth == svn_depth_files)
6485                  shallow_child->missing_child = TRUE;
6486              }
6487            else
6488              {
6489                shallow_child = svn_client__merge_path_create(wc_path,
6490                                                              result_pool);
6491                new_shallow_child = TRUE;
6492
6493                if (*child_depth == svn_depth_empty
6494                    || *child_depth == svn_depth_files)
6495                  shallow_child->missing_child = TRUE;
6496              }
6497
6498           /* A little trickery: If PATH doesn't have any mergeinfo or has
6499              only inheritable mergeinfo, we still describe it as having
6500              non-inheritable mergeinfo if it is missing a child due to
6501              a shallow depth.  Why? Because the mergeinfo we'll add to PATH
6502              to describe the merge must be non-inheritable, so PATH's missing
6503              children don't inherit it.  Marking these PATHs as non-
6504              inheritable allows the logic for case 3 to properly account
6505              for PATH's children. */
6506           if (!shallow_child->has_noninheritable
6507               && (*child_depth == svn_depth_empty
6508                   || *child_depth == svn_depth_files))
6509             {
6510               shallow_child->has_noninheritable = TRUE;
6511             }
6512
6513           if (new_shallow_child)
6514             insert_child_to_merge(children_with_mergeinfo, shallow_child,
6515                                   result_pool);
6516        }
6517     }
6518
6519   /* Case 6: Paths absent from disk due to server or user exclusion. */
6520   SVN_ERR(svn_wc__get_excluded_subtrees(&excluded_subtrees,
6521                                         ctx->wc_ctx, target->abspath,
6522                                         result_pool, scratch_pool));
6523   if (excluded_subtrees)
6524     {
6525       apr_hash_index_t *hi;
6526
6527       for (hi = apr_hash_first(scratch_pool, excluded_subtrees);
6528            hi;
6529            hi = apr_hash_next(hi))
6530         {
6531            const char *wc_path = svn__apr_hash_index_key(hi);
6532            svn_client__merge_path_t *child = get_child_with_mergeinfo(
6533              children_with_mergeinfo, wc_path);
6534
6535            if (child)
6536              {
6537                child->absent = TRUE;
6538              }
6539            else
6540              {
6541                svn_client__merge_path_t *absent_child =
6542                  svn_client__merge_path_create(wc_path, result_pool);
6543                absent_child->absent = TRUE;
6544                insert_child_to_merge(children_with_mergeinfo, absent_child,
6545                                      result_pool);
6546              }
6547         }
6548     }
6549
6550   /* Case 7: The merge target MERGE_CMD_BATON->target->abspath is always
6551      present. */
6552   if (!get_child_with_mergeinfo(children_with_mergeinfo,
6553                                 target->abspath))
6554     {
6555       svn_client__merge_path_t *target_child =
6556         svn_client__merge_path_create(target->abspath,
6557                                       result_pool);
6558       insert_child_to_merge(children_with_mergeinfo, target_child,
6559                             result_pool);
6560     }
6561
6562   /* Case 8: Path is an immediate *directory* child of
6563      MERGE_CMD_BATON->target->abspath and DEPTH is svn_depth_immediates.
6564
6565      Case 9: Path is an immediate *file* child of
6566      MERGE_CMD_BATON->target->abspath and DEPTH is svn_depth_files. */
6567   if (depth == svn_depth_immediates || depth == svn_depth_files)
6568     {
6569       int j;
6570       const apr_array_header_t *immediate_children;
6571
6572       SVN_ERR(svn_wc__node_get_children_of_working_node(
6573         &immediate_children, ctx->wc_ctx,
6574         target->abspath, FALSE, scratch_pool, scratch_pool));
6575
6576       for (j = 0; j < immediate_children->nelts; j++)
6577         {
6578           const char *immediate_child_abspath =
6579             APR_ARRAY_IDX(immediate_children, j, const char *);
6580           svn_node_kind_t immediate_child_kind;
6581
6582           svn_pool_clear(iterpool);
6583           SVN_ERR(svn_wc_read_kind2(&immediate_child_kind,
6584                                     ctx->wc_ctx, immediate_child_abspath,
6585                                     FALSE, FALSE, iterpool));
6586           if ((immediate_child_kind == svn_node_dir
6587                && depth == svn_depth_immediates)
6588               || (immediate_child_kind == svn_node_file
6589                   && depth == svn_depth_files))
6590             {
6591               if (!get_child_with_mergeinfo(children_with_mergeinfo,
6592                                             immediate_child_abspath))
6593                 {
6594                   svn_client__merge_path_t *immediate_child =
6595                     svn_client__merge_path_create(immediate_child_abspath,
6596                                                   result_pool);
6597
6598                   if (immediate_child_kind == svn_node_dir
6599                       && depth == svn_depth_immediates)
6600                     immediate_child->immediate_child_dir = TRUE;
6601
6602                   insert_child_to_merge(children_with_mergeinfo,
6603                                         immediate_child, result_pool);
6604                 }
6605             }
6606         }
6607     }
6608
6609   /* If DEPTH isn't empty then cover cases 3), 4), and 5), possibly adding
6610      elements to CHILDREN_WITH_MERGEINFO. */
6611   if (depth <= svn_depth_empty)
6612     return SVN_NO_ERROR;
6613
6614   for (i = 0; i < children_with_mergeinfo->nelts; i++)
6615     {
6616       svn_client__merge_path_t *child =
6617         APR_ARRAY_IDX(children_with_mergeinfo, i,
6618                       svn_client__merge_path_t *);
6619       svn_pool_clear(iterpool);
6620
6621       /* Case 3) Where merging to a path with a switched child the path
6622          gets non-inheritable mergeinfo for the merge range performed and
6623          the child gets its own set of mergeinfo.  If the switched child
6624          later "returns", e.g. a switched path is unswitched, the child
6625          may not have any explicit mergeinfo.  If the initial merge is
6626          repeated we don't want to repeat the merge for the path, but we
6627          do want to repeat it for the previously switched child.  To
6628          ensure this we check if all of CHILD's non-missing children have
6629          explicit mergeinfo (they should already be present in
6630          CHILDREN_WITH_MERGEINFO if they do).  If not,
6631          add the children without mergeinfo to CHILDREN_WITH_MERGEINFO so
6632          do_directory_merge() will merge them independently.
6633
6634          But that's not enough!  Since do_directory_merge() performs
6635          the merges on the paths in CHILDREN_WITH_MERGEINFO in a depth
6636          first manner it will merge the previously switched path's parent
6637          first.  As part of this merge it will update the parent's
6638          previously non-inheritable mergeinfo and make it inheritable
6639          (since it notices the path has no missing children), then when
6640          do_directory_merge() finally merges the previously missing
6641          child it needs to get mergeinfo from the child's nearest
6642          ancestor, but since do_directory_merge() already tweaked that
6643          mergeinfo, removing the non-inheritable flag, it appears that the
6644          child already has been merged to.  To prevent this we set
6645          override mergeinfo on the child now, before any merging is done,
6646          so it has explicit mergeinfo that reflects only CHILD's
6647          inheritable mergeinfo. */
6648
6649       /* If depth is immediates or files then don't add new children if
6650          CHILD is a subtree of the merge target; those children are below
6651          the operational depth of the merge. */
6652       if (child->has_noninheritable
6653           && (i == 0 || depth == svn_depth_infinity))
6654         {
6655           const apr_array_header_t *children;
6656           int j;
6657
6658           SVN_ERR(svn_wc__node_get_children(&children,
6659                                             ctx->wc_ctx,
6660                                             child->abspath, FALSE,
6661                                             iterpool, iterpool));
6662           for (j = 0; j < children->nelts; j++)
6663             {
6664               svn_client__merge_path_t *child_of_noninheritable;
6665               const char *child_abspath = APR_ARRAY_IDX(children, j,
6666                                                         const char*);
6667
6668               /* Does this child already exist in CHILDREN_WITH_MERGEINFO?
6669                  If not, create it and insert it into
6670                  CHILDREN_WITH_MERGEINFO and set override mergeinfo on
6671                  it. */
6672               child_of_noninheritable =
6673                 get_child_with_mergeinfo(children_with_mergeinfo,
6674                                          child_abspath);
6675               if (!child_of_noninheritable)
6676                 {
6677                   /* Don't add directory children if DEPTH
6678                      is svn_depth_files. */
6679                   if (depth == svn_depth_files)
6680                     {
6681                       svn_node_kind_t child_kind;
6682                       SVN_ERR(svn_wc_read_kind2(&child_kind,
6683                                                 ctx->wc_ctx, child_abspath,
6684                                                 FALSE, FALSE, iterpool));
6685                       if (child_kind != svn_node_file)
6686                         continue;
6687                     }
6688                   /* else DEPTH is infinity or immediates so we want both
6689                      directory and file children. */
6690
6691                   child_of_noninheritable =
6692                     svn_client__merge_path_create(child_abspath, result_pool);
6693                   child_of_noninheritable->child_of_noninheritable = TRUE;
6694                   insert_child_to_merge(children_with_mergeinfo,
6695                                         child_of_noninheritable,
6696                                         result_pool);
6697                   if (!dry_run && same_repos)
6698                     {
6699                       svn_mergeinfo_t mergeinfo;
6700
6701                       SVN_ERR(svn_client__get_wc_mergeinfo(
6702                         &mergeinfo, NULL,
6703                         svn_mergeinfo_nearest_ancestor,
6704                         child_of_noninheritable->abspath,
6705                         target->abspath, NULL, FALSE,
6706                         ctx, iterpool, iterpool));
6707
6708                       SVN_ERR(svn_client__record_wc_mergeinfo(
6709                         child_of_noninheritable->abspath, mergeinfo,
6710                         FALSE, ctx, iterpool));
6711                     }
6712                 }
6713             }
6714         }
6715       /* Case 4 and 5 are handled by the following function. */
6716       SVN_ERR(insert_parent_and_sibs_of_sw_absent_del_subtree(
6717         children_with_mergeinfo, target, &i, child,
6718         depth, ctx, result_pool));
6719     } /* i < children_with_mergeinfo->nelts */
6720   svn_pool_destroy(iterpool);
6721
6722   return SVN_NO_ERROR;
6723 }
6724
6725
6726 /* Implements the svn_log_entry_receiver_t interface.
6727  *
6728  * BATON is an 'apr_array_header_t *' array of 'svn_revnum_t'.
6729  * Push a copy of LOG_ENTRY->revision onto BATON.  Thus, a
6730  * series of invocations of this callback accumulates the
6731  * corresponding set of revisions into BATON.
6732  */
6733 static svn_error_t *
6734 log_changed_revs(void *baton,
6735                  svn_log_entry_t *log_entry,
6736                  apr_pool_t *pool)
6737 {
6738   apr_array_header_t *revs = baton;
6739
6740   APR_ARRAY_PUSH(revs, svn_revnum_t) = log_entry->revision;
6741   return SVN_NO_ERROR;
6742 }
6743
6744
6745 /* Set *MIN_REV_P to the oldest and *MAX_REV_P to the youngest start or end
6746  * revision occurring in RANGELIST, or to SVN_INVALID_REVNUM if RANGELIST
6747  * is empty. */
6748 static void
6749 merge_range_find_extremes(svn_revnum_t *min_rev_p,
6750                           svn_revnum_t *max_rev_p,
6751                           const svn_rangelist_t *rangelist)
6752 {
6753   int i;
6754
6755   *min_rev_p = SVN_INVALID_REVNUM;
6756   *max_rev_p = SVN_INVALID_REVNUM;
6757   for (i = 0; i < rangelist->nelts; i++)
6758     {
6759       svn_merge_range_t *range
6760         = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
6761       svn_revnum_t range_min = MIN(range->start, range->end);
6762       svn_revnum_t range_max = MAX(range->start, range->end);
6763
6764       if ((! SVN_IS_VALID_REVNUM(*min_rev_p)) || (range_min < *min_rev_p))
6765         *min_rev_p = range_min;
6766       if ((! SVN_IS_VALID_REVNUM(*max_rev_p)) || (range_max > *max_rev_p))
6767         *max_rev_p = range_max;
6768     }
6769 }
6770
6771 /* Wrapper around svn_ra_get_log2(). Invoke RECEIVER with RECEIVER_BATON
6772  * on each commit from YOUNGEST_REV to OLDEST_REV in which TARGET_RELPATH
6773  * changed.  TARGET_RELPATH is relative to RA_SESSION's URL.
6774  * Important: Revision properties are not retrieved by this function for
6775  * performance reasons.
6776  */
6777 static svn_error_t *
6778 get_log(svn_ra_session_t *ra_session,
6779         const char *target_relpath,
6780         svn_revnum_t youngest_rev,
6781         svn_revnum_t oldest_rev,
6782         svn_boolean_t discover_changed_paths,
6783         svn_log_entry_receiver_t receiver,
6784         void *receiver_baton,
6785         apr_pool_t *pool)
6786 {
6787   apr_array_header_t *log_targets;
6788   apr_array_header_t *revprops;
6789
6790   log_targets = apr_array_make(pool, 1, sizeof(const char *));
6791   APR_ARRAY_PUSH(log_targets, const char *) = target_relpath;
6792
6793   revprops = apr_array_make(pool, 0, sizeof(const char *));
6794
6795   SVN_ERR(svn_ra_get_log2(ra_session, log_targets, youngest_rev,
6796                           oldest_rev, 0 /* limit */, discover_changed_paths,
6797                           FALSE /* strict_node_history */,
6798                           FALSE /* include_merged_revisions */,
6799                           revprops, receiver, receiver_baton, pool));
6800
6801   return SVN_NO_ERROR;
6802 }
6803
6804 /* Set *OPERATIVE_RANGES_P to an array of svn_merge_range_t * merge
6805    range objects copied wholesale from RANGES which have the property
6806    that in some revision within that range the object identified by
6807    RA_SESSION was modified (if by "modified" we mean "'svn log' would
6808    return that revision).  *OPERATIVE_RANGES_P is allocated from the
6809    same pool as RANGES, and the ranges within it are shared with
6810    RANGES, too.
6811
6812    *OPERATIVE_RANGES_P may be the same as RANGES (that is, the output
6813    parameter is set only after the input is no longer used).
6814
6815    Use POOL for temporary allocations.  */
6816 static svn_error_t *
6817 remove_noop_merge_ranges(svn_rangelist_t **operative_ranges_p,
6818                          svn_ra_session_t *ra_session,
6819                          const svn_rangelist_t *ranges,
6820                          apr_pool_t *pool)
6821 {
6822   int i;
6823   svn_revnum_t oldest_rev, youngest_rev;
6824   apr_array_header_t *changed_revs =
6825     apr_array_make(pool, ranges->nelts, sizeof(svn_revnum_t));
6826   svn_rangelist_t *operative_ranges =
6827     apr_array_make(ranges->pool, ranges->nelts, ranges->elt_size);
6828
6829   /* Find the revision extremes of the RANGES we have. */
6830   merge_range_find_extremes(&oldest_rev, &youngest_rev, ranges);
6831   if (SVN_IS_VALID_REVNUM(oldest_rev))
6832     oldest_rev++;  /* make it inclusive */
6833
6834   /* Get logs across those ranges, recording which revisions hold
6835      changes to our object's history. */
6836   SVN_ERR(get_log(ra_session, "", youngest_rev, oldest_rev, FALSE,
6837                   log_changed_revs, changed_revs, pool));
6838
6839   /* Are there *any* changes? */
6840   if (changed_revs->nelts)
6841     {
6842       /* Our list of changed revisions should be in youngest-to-oldest
6843          order. */
6844       svn_revnum_t youngest_changed_rev
6845         = APR_ARRAY_IDX(changed_revs, 0, svn_revnum_t);
6846       svn_revnum_t oldest_changed_rev
6847         = APR_ARRAY_IDX(changed_revs, changed_revs->nelts - 1, svn_revnum_t);
6848
6849       /* Now, copy from RANGES to *OPERATIVE_RANGES, filtering out ranges
6850          that aren't operative (by virtue of not having any revisions
6851          represented in the CHANGED_REVS array). */
6852       for (i = 0; i < ranges->nelts; i++)
6853         {
6854           svn_merge_range_t *range = APR_ARRAY_IDX(ranges, i,
6855                                                    svn_merge_range_t *);
6856           svn_revnum_t range_min = MIN(range->start, range->end) + 1;
6857           svn_revnum_t range_max = MAX(range->start, range->end);
6858           int j;
6859
6860           /* If the merge range is entirely outside the range of changed
6861              revisions, we've no use for it. */
6862           if ((range_min > youngest_changed_rev)
6863               || (range_max < oldest_changed_rev))
6864             continue;
6865
6866           /* Walk through the changed_revs to see if any of them fall
6867              inside our current range. */
6868           for (j = 0; j < changed_revs->nelts; j++)
6869             {
6870               svn_revnum_t changed_rev
6871                 = APR_ARRAY_IDX(changed_revs, j, svn_revnum_t);
6872               if ((changed_rev >= range_min) && (changed_rev <= range_max))
6873                 {
6874                   APR_ARRAY_PUSH(operative_ranges, svn_merge_range_t *) =
6875                     range;
6876                   break;
6877                 }
6878             }
6879         }
6880     }
6881
6882   *operative_ranges_p = operative_ranges;
6883   return SVN_NO_ERROR;
6884 }
6885
6886
6887 /*-----------------------------------------------------------------------*/
6888 \f
6889 /*** Merge Source Normalization ***/
6890
6891 /* qsort-compatible sort routine, rating merge_source_t * objects to
6892    be in descending (youngest-to-oldest) order based on their ->loc1->rev
6893    component. */
6894 static int
6895 compare_merge_source_ts(const void *a,
6896                         const void *b)
6897 {
6898   svn_revnum_t a_rev = (*(const merge_source_t *const *)a)->loc1->rev;
6899   svn_revnum_t b_rev = (*(const merge_source_t *const *)b)->loc1->rev;
6900   if (a_rev == b_rev)
6901     return 0;
6902   return a_rev < b_rev ? 1 : -1;
6903 }
6904
6905 /* Set *MERGE_SOURCE_TS_P to a list of merge sources generated by
6906    slicing history location SEGMENTS with a given requested merge
6907    RANGE.  Use SOURCE_LOC for full source URL calculation.
6908
6909    Order the merge sources in *MERGE_SOURCE_TS_P from oldest to
6910    youngest. */
6911 static svn_error_t *
6912 combine_range_with_segments(apr_array_header_t **merge_source_ts_p,
6913                             const svn_merge_range_t *range,
6914                             const apr_array_header_t *segments,
6915                             const svn_client__pathrev_t *source_loc,
6916                             apr_pool_t *pool)
6917 {
6918   apr_array_header_t *merge_source_ts =
6919     apr_array_make(pool, 1, sizeof(merge_source_t *));
6920   svn_revnum_t minrev = MIN(range->start, range->end) + 1;
6921   svn_revnum_t maxrev = MAX(range->start, range->end);
6922   svn_boolean_t subtractive = (range->start > range->end);
6923   int i;
6924
6925   for (i = 0; i < segments->nelts; i++)
6926     {
6927       svn_location_segment_t *segment =
6928         APR_ARRAY_IDX(segments, i, svn_location_segment_t *);
6929       svn_client__pathrev_t *loc1, *loc2;
6930       merge_source_t *merge_source;
6931       const char *path1 = NULL;
6932       svn_revnum_t rev1;
6933
6934       /* If this segment doesn't overlap our range at all, or
6935          represents a gap, ignore it. */
6936       if ((segment->range_end < minrev)
6937           || (segment->range_start > maxrev)
6938           || (! segment->path))
6939         continue;
6940
6941       /* If our range spans a segment boundary, we have to point our
6942          merge_source_t's path1 to the path of the immediately older
6943          segment, else it points to the same location as its path2.  */
6944       rev1 = MAX(segment->range_start, minrev) - 1;
6945       if (minrev <= segment->range_start)
6946         {
6947           if (i > 0)
6948             {
6949               path1 = (APR_ARRAY_IDX(segments, i - 1,
6950                                      svn_location_segment_t *))->path;
6951             }
6952           /* If we've backed PATH1 up into a segment gap, let's back
6953              it up further still to the segment before the gap.  We'll
6954              have to adjust rev1, too. */
6955           if ((! path1) && (i > 1))
6956             {
6957               path1 = (APR_ARRAY_IDX(segments, i - 2,
6958                                      svn_location_segment_t *))->path;
6959               rev1 = (APR_ARRAY_IDX(segments, i - 2,
6960                                     svn_location_segment_t *))->range_end;
6961             }
6962         }
6963       else
6964         {
6965           path1 = apr_pstrdup(pool, segment->path);
6966         }
6967
6968       /* If we don't have two valid paths, we won't know what to do
6969          when merging.  This could happen if someone requested a merge
6970          where the source didn't exist in a particular revision or
6971          something.  The merge code would probably bomb out anyway, so
6972          we'll just *not* create a merge source in this case. */
6973       if (! (path1 && segment->path))
6974         continue;
6975
6976       /* Build our merge source structure. */
6977       loc1 = svn_client__pathrev_create_with_relpath(
6978                source_loc->repos_root_url, source_loc->repos_uuid,
6979                rev1, path1, pool);
6980       loc2 = svn_client__pathrev_create_with_relpath(
6981                source_loc->repos_root_url, source_loc->repos_uuid,
6982                MIN(segment->range_end, maxrev), segment->path, pool);
6983       /* If this is subtractive, reverse the whole calculation. */
6984       if (subtractive)
6985         merge_source = merge_source_create(loc2, loc1, TRUE /* ancestral */,
6986                                            pool);
6987       else
6988         merge_source = merge_source_create(loc1, loc2, TRUE /* ancestral */,
6989                                            pool);
6990
6991       APR_ARRAY_PUSH(merge_source_ts, merge_source_t *) = merge_source;
6992     }
6993
6994   /* If this was a subtractive merge, and we created more than one
6995      merge source, we need to reverse the sort ordering of our sources. */
6996   if (subtractive && (merge_source_ts->nelts > 1))
6997     qsort(merge_source_ts->elts, merge_source_ts->nelts,
6998           merge_source_ts->elt_size, compare_merge_source_ts);
6999
7000   *merge_source_ts_p = merge_source_ts;
7001   return SVN_NO_ERROR;
7002 }
7003
7004 /* Similar to normalize_merge_sources() except the input MERGE_RANGE_TS is a
7005  * rangelist.
7006  */
7007 static svn_error_t *
7008 normalize_merge_sources_internal(apr_array_header_t **merge_sources_p,
7009                                  const svn_client__pathrev_t *source_loc,
7010                                  const svn_rangelist_t *merge_range_ts,
7011                                  svn_ra_session_t *ra_session,
7012                                  svn_client_ctx_t *ctx,
7013                                  apr_pool_t *result_pool,
7014                                  apr_pool_t *scratch_pool)
7015 {
7016   svn_revnum_t source_peg_revnum = source_loc->rev;
7017   svn_revnum_t oldest_requested, youngest_requested;
7018   svn_revnum_t trim_revision = SVN_INVALID_REVNUM;
7019   apr_array_header_t *segments;
7020   int i;
7021
7022   /* Initialize our return variable. */
7023   *merge_sources_p = apr_array_make(result_pool, 1, sizeof(merge_source_t *));
7024
7025   /* No ranges to merge?  No problem. */
7026   if (merge_range_ts->nelts == 0)
7027     return SVN_NO_ERROR;
7028
7029   /* Find the extremes of the revisions across our set of ranges. */
7030   merge_range_find_extremes(&oldest_requested, &youngest_requested,
7031                             merge_range_ts);
7032
7033   /* ### FIXME:  Our underlying APIs can't yet handle the case where
7034      the peg revision isn't the youngest of the three revisions.  So
7035      we'll just verify that the source in the peg revision is related
7036      to the source in the youngest requested revision (which is
7037      all the underlying APIs would do in this case right now anyway). */
7038   if (source_peg_revnum < youngest_requested)
7039     {
7040       svn_client__pathrev_t *start_loc;
7041
7042       SVN_ERR(svn_client__repos_location(&start_loc,
7043                                          ra_session, source_loc,
7044                                          youngest_requested,
7045                                          ctx, scratch_pool, scratch_pool));
7046       source_peg_revnum = youngest_requested;
7047     }
7048
7049   /* Fetch the locations for our merge range span. */
7050   SVN_ERR(svn_client__repos_location_segments(&segments,
7051                                               ra_session, source_loc->url,
7052                                               source_peg_revnum,
7053                                               youngest_requested,
7054                                               oldest_requested,
7055                                               ctx, result_pool));
7056
7057   /* See if we fetched enough history to do the job.  "Surely we did,"
7058      you say.  "After all, we covered the entire requested merge
7059      range."  Yes, that's true, but if our first segment doesn't
7060      extend back to the oldest request revision, we've got a special
7061      case to deal with.  Or if the first segment represents a gap,
7062      that's another special case.  */
7063   trim_revision = SVN_INVALID_REVNUM;
7064   if (segments->nelts)
7065     {
7066       svn_location_segment_t *first_segment =
7067         APR_ARRAY_IDX(segments, 0, svn_location_segment_t *);
7068
7069       /* If the first segment doesn't start with the OLDEST_REQUESTED
7070          revision, we'll need to pass a trim revision to our range
7071          cruncher. */
7072       if (first_segment->range_start != oldest_requested)
7073         {
7074           trim_revision = first_segment->range_start;
7075         }
7076
7077       /* Else, if the first segment has no path (and therefore is a
7078          gap), then we'll fetch the copy source revision from the
7079          second segment (provided there is one, of course) and use it
7080          to prepend an extra pathful segment to our list.
7081
7082          ### We could avoid this bit entirely if we'd passed
7083          ### SVN_INVALID_REVNUM instead of OLDEST_REQUESTED to
7084          ### svn_client__repos_location_segments(), but that would
7085          ### really penalize clients hitting pre-1.5 repositories with
7086          ### the typical small merge range request (because of the
7087          ### lack of a node-origins cache in the repository).  */
7088       else if (! first_segment->path)
7089         {
7090           if (segments->nelts > 1)
7091             {
7092               svn_location_segment_t *second_segment =
7093                 APR_ARRAY_IDX(segments, 1, svn_location_segment_t *);
7094               const char *segment_url;
7095               const char *original_repos_relpath;
7096               svn_revnum_t original_revision;
7097               svn_opt_revision_t range_start_rev;
7098               range_start_rev.kind = svn_opt_revision_number;
7099               range_start_rev.value.number = second_segment->range_start;
7100
7101               segment_url = svn_path_url_add_component2(
7102                               source_loc->repos_root_url, second_segment->path,
7103                               scratch_pool);
7104               SVN_ERR(svn_client__get_copy_source(&original_repos_relpath,
7105                                                   &original_revision,
7106                                                   segment_url,
7107                                                   &range_start_rev, ctx,
7108                                                   result_pool, scratch_pool));
7109               /* Got copyfrom data?  Fix up the first segment to cover
7110                  back to COPYFROM_REV + 1, and then prepend a new
7111                  segment covering just COPYFROM_REV. */
7112               if (original_repos_relpath)
7113                 {
7114                   svn_location_segment_t *new_segment =
7115                     apr_pcalloc(result_pool, sizeof(*new_segment));
7116
7117                   new_segment->path = original_repos_relpath;
7118                   new_segment->range_start = original_revision;
7119                   new_segment->range_end = original_revision;
7120                   svn_sort__array_insert(&new_segment, segments, 0);
7121                 }
7122             }
7123         }
7124     }
7125
7126   /* For each range in our requested range set, try to determine the
7127      path(s) associated with that range.  */
7128   for (i = 0; i < merge_range_ts->nelts; i++)
7129     {
7130       svn_merge_range_t *range =
7131         APR_ARRAY_IDX(merge_range_ts, i, svn_merge_range_t *);
7132       apr_array_header_t *merge_sources;
7133
7134       if (SVN_IS_VALID_REVNUM(trim_revision))
7135         {
7136           /* If the range predates the trim revision, discard it. */
7137           if (MAX(range->start, range->end) < trim_revision)
7138             continue;
7139
7140           /* If the range overlaps the trim revision, trim it. */
7141           if (range->start < trim_revision)
7142             range->start = trim_revision;
7143           if (range->end < trim_revision)
7144             range->end = trim_revision;
7145         }
7146
7147       /* Copy the resulting merge sources into master list thereof. */
7148       SVN_ERR(combine_range_with_segments(&merge_sources, range,
7149                                           segments, source_loc,
7150                                           result_pool));
7151       apr_array_cat(*merge_sources_p, merge_sources);
7152     }
7153
7154   return SVN_NO_ERROR;
7155 }
7156
7157 /* Determine the normalized ranges to merge from a given line of history.
7158
7159    Calculate the result by intersecting the list of location segments at
7160    which SOURCE_LOC existed along its line of history with the requested
7161    revision ranges in RANGES_TO_MERGE.  RANGES_TO_MERGE is an array of
7162    (svn_opt_revision_range_t *) revision ranges.  Use SOURCE_PATH_OR_URL to
7163    resolve any WC-relative revision specifiers (such as 'base') in
7164    RANGES_TO_MERGE.
7165
7166    Set *MERGE_SOURCES_P to an array of merge_source_t * objects, each
7167    describing a normalized range of revisions to be merged from the line
7168    history of SOURCE_LOC.  Order the objects from oldest to youngest.
7169
7170    RA_SESSION is an RA session open to the repository of SOURCE_LOC; it may
7171    be temporarily reparented within this function.  Use RA_SESSION to find
7172    the location segments along the line of history of SOURCE_LOC.
7173
7174    Allocate MERGE_SOURCES_P and its contents in RESULT_POOL.
7175
7176    See `MERGEINFO MERGE SOURCE NORMALIZATION' for more on the
7177    background of this function.
7178 */
7179 static svn_error_t *
7180 normalize_merge_sources(apr_array_header_t **merge_sources_p,
7181                         const char *source_path_or_url,
7182                         const svn_client__pathrev_t *source_loc,
7183                         const apr_array_header_t *ranges_to_merge,
7184                         svn_ra_session_t *ra_session,
7185                         svn_client_ctx_t *ctx,
7186                         apr_pool_t *result_pool,
7187                         apr_pool_t *scratch_pool)
7188 {
7189   const char *source_abspath_or_url;
7190   svn_revnum_t youngest_rev = SVN_INVALID_REVNUM;
7191   svn_rangelist_t *merge_range_ts;
7192   int i;
7193   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
7194
7195   if(!svn_path_is_url(source_path_or_url))
7196     SVN_ERR(svn_dirent_get_absolute(&source_abspath_or_url, source_path_or_url,
7197                                     scratch_pool));
7198   else
7199     source_abspath_or_url = source_path_or_url;
7200
7201   /* Create a list to hold svn_merge_range_t's. */
7202   merge_range_ts = apr_array_make(scratch_pool, ranges_to_merge->nelts,
7203                                   sizeof(svn_merge_range_t *));
7204
7205   for (i = 0; i < ranges_to_merge->nelts; i++)
7206     {
7207       svn_opt_revision_range_t *range
7208         = APR_ARRAY_IDX(ranges_to_merge, i, svn_opt_revision_range_t *);
7209       svn_merge_range_t mrange;
7210
7211       svn_pool_clear(iterpool);
7212
7213       /* Resolve revisions to real numbers, validating as we go. */
7214       if ((range->start.kind == svn_opt_revision_unspecified)
7215           || (range->end.kind == svn_opt_revision_unspecified))
7216         return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL,
7217                                 _("Not all required revisions are specified"));
7218
7219       SVN_ERR(svn_client__get_revision_number(&mrange.start, &youngest_rev,
7220                                               ctx->wc_ctx,
7221                                               source_abspath_or_url,
7222                                               ra_session, &range->start,
7223                                               iterpool));
7224       SVN_ERR(svn_client__get_revision_number(&mrange.end, &youngest_rev,
7225                                               ctx->wc_ctx,
7226                                               source_abspath_or_url,
7227                                               ra_session, &range->end,
7228                                               iterpool));
7229
7230       /* If this isn't a no-op range... */
7231       if (mrange.start != mrange.end)
7232         {
7233           /* ...then add it to the list. */
7234           mrange.inheritable = TRUE;
7235           APR_ARRAY_PUSH(merge_range_ts, svn_merge_range_t *)
7236             = svn_merge_range_dup(&mrange, scratch_pool);
7237         }
7238     }
7239
7240   SVN_ERR(normalize_merge_sources_internal(
7241             merge_sources_p, source_loc,
7242             merge_range_ts, ra_session, ctx, result_pool, scratch_pool));
7243
7244   svn_pool_destroy(iterpool);
7245   return SVN_NO_ERROR;
7246 }
7247
7248
7249 /*-----------------------------------------------------------------------*/
7250 \f
7251 /*** Merge Workhorse Functions ***/
7252
7253 /* Helper for do_directory_merge() and do_file_merge() which filters out a
7254    path's own natural history from the mergeinfo describing a merge.
7255
7256    Given the natural history IMPLICIT_MERGEINFO of some wc merge target path,
7257    the repository-relative merge source path SOURCE_REL_PATH, and the
7258    requested merge range REQUESTED_RANGE from SOURCE_REL_PATH, remove any
7259    portion of REQUESTED_RANGE which is already described in
7260    IMPLICIT_MERGEINFO.  Store the result in *FILTERED_RANGELIST.
7261
7262    This function only filters natural history for mergeinfo that will be
7263    *added* during a forward merge.  Removing natural history from explicit
7264    mergeinfo is harmless.  If REQUESTED_RANGE describes a reverse merge,
7265    then *FILTERED_RANGELIST is simply populated with one range described
7266    by REQUESTED_RANGE.  *FILTERED_RANGELIST is never NULL.
7267
7268    Allocate *FILTERED_RANGELIST in POOL. */
7269 static svn_error_t *
7270 filter_natural_history_from_mergeinfo(svn_rangelist_t **filtered_rangelist,
7271                                       const char *source_rel_path,
7272                                       svn_mergeinfo_t implicit_mergeinfo,
7273                                       svn_merge_range_t *requested_range,
7274                                       apr_pool_t *pool)
7275 {
7276   /* Make the REQUESTED_RANGE into a rangelist. */
7277   svn_rangelist_t *requested_rangelist =
7278     svn_rangelist__initialize(requested_range->start, requested_range->end,
7279                               requested_range->inheritable, pool);
7280
7281   *filtered_rangelist = NULL;
7282
7283   /* For forward merges: If the IMPLICIT_MERGEINFO already describes ranges
7284      associated with SOURCE_REL_PATH then filter those ranges out. */
7285   if (implicit_mergeinfo
7286       && (requested_range->start < requested_range->end))
7287     {
7288       svn_rangelist_t *implied_rangelist =
7289                         svn_hash_gets(implicit_mergeinfo, source_rel_path);
7290
7291       if (implied_rangelist)
7292         SVN_ERR(svn_rangelist_remove(filtered_rangelist,
7293                                      implied_rangelist,
7294                                      requested_rangelist,
7295                                      FALSE, pool));
7296     }
7297
7298   /* If no filtering was performed the filtered rangelist is
7299      simply the requested rangelist.*/
7300   if (! (*filtered_rangelist))
7301     *filtered_rangelist = requested_rangelist;
7302
7303   return SVN_NO_ERROR;
7304 }
7305
7306 /* Return a merge source representing the sub-range from START_REV to
7307    END_REV of SOURCE.  SOURCE obeys the rules described in the
7308    'MERGEINFO MERGE SOURCE NORMALIZATION' comment at the top of this file.
7309    The younger of START_REV and END_REV is inclusive while the older is
7310    exclusive.
7311
7312    Allocate the result structure in POOL but leave the URLs in it as shallow
7313    copies of the URLs in SOURCE.
7314 */
7315 static merge_source_t *
7316 subrange_source(const merge_source_t *source,
7317                 svn_revnum_t start_rev,
7318                 svn_revnum_t end_rev,
7319                 apr_pool_t *pool)
7320 {
7321   svn_boolean_t is_rollback = (source->loc1->rev > source->loc2->rev);
7322   svn_boolean_t same_urls = (strcmp(source->loc1->url, source->loc2->url) == 0);
7323   svn_client__pathrev_t loc1 = *source->loc1;
7324   svn_client__pathrev_t loc2 = *source->loc2;
7325
7326   /* For this function we require that the input source is 'ancestral'. */
7327   SVN_ERR_ASSERT_NO_RETURN(source->ancestral);
7328   SVN_ERR_ASSERT_NO_RETURN(start_rev != end_rev);
7329
7330   loc1.rev = start_rev;
7331   loc2.rev = end_rev;
7332   if (! same_urls)
7333     {
7334       if (is_rollback && (end_rev != source->loc2->rev))
7335         {
7336           loc2.url = source->loc1->url;
7337         }
7338       if ((! is_rollback) && (start_rev != source->loc1->rev))
7339         {
7340           loc1.url = source->loc2->url;
7341         }
7342     }
7343   return merge_source_create(&loc1, &loc2, source->ancestral, pool);
7344 }
7345
7346 /* The single-file, simplified version of do_directory_merge(), which see for
7347    parameter descriptions.
7348
7349    Additional parameters:
7350
7351    If SOURCES_RELATED is set, the "left" and "right" sides of SOURCE are
7352    historically related (ancestors, uncles, second
7353    cousins thrice removed, etc...).  (This is used to simulate the
7354    history checks that the repository logic does in the directory case.)
7355
7356    If mergeinfo is being recorded to describe this merge, and RESULT_CATALOG
7357    is not NULL, then don't record the new mergeinfo on the TARGET_ABSPATH,
7358    but instead record it in RESULT_CATALOG, where the key is TARGET_ABSPATH
7359    and the value is the new mergeinfo for that path.  Allocate additions
7360    to RESULT_CATALOG in pool which RESULT_CATALOG was created in.
7361
7362    CONFLICTED_RANGE is as documented for do_directory_merge().
7363
7364    Note: MERGE_B->RA_SESSION1 must be associated with SOURCE->loc1->url and
7365    MERGE_B->RA_SESSION2 with SOURCE->loc2->url.
7366 */
7367 static svn_error_t *
7368 do_file_merge(svn_mergeinfo_catalog_t result_catalog,
7369               single_range_conflict_report_t **conflict_report,
7370               const merge_source_t *source,
7371               const char *target_abspath,
7372               const svn_diff_tree_processor_t *processor,
7373               svn_boolean_t sources_related,
7374               svn_boolean_t squelch_mergeinfo_notifications,
7375               merge_cmd_baton_t *merge_b,
7376               apr_pool_t *result_pool,
7377               apr_pool_t *scratch_pool)
7378 {
7379   svn_rangelist_t *remaining_ranges;
7380   svn_client_ctx_t *ctx = merge_b->ctx;
7381   svn_merge_range_t range;
7382   svn_mergeinfo_t target_mergeinfo;
7383   svn_boolean_t inherited = FALSE;
7384   svn_boolean_t is_rollback = (source->loc1->rev > source->loc2->rev);
7385   const svn_client__pathrev_t *primary_src
7386     = is_rollback ? source->loc1 : source->loc2;
7387   svn_boolean_t honor_mergeinfo = HONOR_MERGEINFO(merge_b);
7388   svn_client__merge_path_t *merge_target = NULL;
7389   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
7390
7391   SVN_ERR_ASSERT(svn_dirent_is_absolute(target_abspath));
7392
7393   *conflict_report = NULL;
7394
7395   /* Note that this is a single-file merge. */
7396   range.start = source->loc1->rev;
7397   range.end = source->loc2->rev;
7398   range.inheritable = TRUE;
7399
7400   merge_target = svn_client__merge_path_create(target_abspath, scratch_pool);
7401
7402   if (honor_mergeinfo)
7403     {
7404       svn_error_t *err;
7405
7406       /* Fetch mergeinfo. */
7407       err = get_full_mergeinfo(&target_mergeinfo,
7408                                &(merge_target->implicit_mergeinfo),
7409                                &inherited, svn_mergeinfo_inherited,
7410                                merge_b->ra_session1, target_abspath,
7411                                MAX(source->loc1->rev, source->loc2->rev),
7412                                MIN(source->loc1->rev, source->loc2->rev),
7413                                ctx, scratch_pool, iterpool);
7414
7415       if (err)
7416         {
7417           if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
7418             {
7419               err = svn_error_createf(
7420                 SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING, err,
7421                 _("Invalid mergeinfo detected on merge target '%s', "
7422                   "merge tracking not possible"),
7423                 svn_dirent_local_style(target_abspath, scratch_pool));
7424             }
7425           return svn_error_trace(err);
7426         }
7427
7428       /* Calculate remaining merges unless this is a record only merge.
7429          In that case the remaining range is the whole range described
7430          by SOURCE->rev1:rev2. */
7431       if (!merge_b->record_only)
7432         {
7433           /* ### Bug?  calculate_remaining_ranges() needs 'source' to adhere
7434            *   to the requirements of 'MERGEINFO MERGE SOURCE NORMALIZATION'
7435            *   here, but it doesn't appear to be guaranteed so. */
7436           SVN_ERR(calculate_remaining_ranges(NULL, merge_target,
7437                                              source,
7438                                              target_mergeinfo,
7439                                              merge_b->implicit_src_gap, FALSE,
7440                                              merge_b->ra_session1,
7441                                              ctx, scratch_pool,
7442                                              iterpool));
7443           remaining_ranges = merge_target->remaining_ranges;
7444
7445           /* We are honoring mergeinfo and this is not a simple record only
7446              merge which blindly records mergeinfo describing the merge of
7447              SOURCE->LOC1->URL@SOURCE->LOC1->REV through
7448              SOURCE->LOC2->URL@SOURCE->LOC2->REV.  This means that the oldest
7449              and youngest revisions merged (as determined above by
7450              calculate_remaining_ranges) might differ from those described
7451              in SOURCE.  To keep the '--- Merging *' notifications consistent
7452              with the '--- Recording mergeinfo *' notifications, we adjust
7453              RANGE to account for such changes. */
7454           if (remaining_ranges->nelts)
7455             {
7456               svn_merge_range_t *adj_start_range =
7457                 APR_ARRAY_IDX(remaining_ranges, 0, svn_merge_range_t *);
7458               svn_merge_range_t *adj_end_range =
7459                 APR_ARRAY_IDX(remaining_ranges, remaining_ranges->nelts - 1,
7460                               svn_merge_range_t *);
7461               range.start = adj_start_range->start;
7462               range.end = adj_end_range->end;
7463             }
7464         }
7465     }
7466
7467   /* The simple cases where our remaining range is SOURCE->rev1:rev2. */
7468   if (!honor_mergeinfo || merge_b->record_only)
7469     {
7470       remaining_ranges = apr_array_make(scratch_pool, 1, sizeof(&range));
7471       APR_ARRAY_PUSH(remaining_ranges, svn_merge_range_t *) = &range;
7472     }
7473
7474   if (!merge_b->record_only)
7475     {
7476       svn_rangelist_t *ranges_to_merge = apr_array_copy(scratch_pool,
7477                                                         remaining_ranges);
7478       const char *target_relpath = "";  /* relative to root of merge */
7479
7480       if (source->ancestral)
7481         {
7482           apr_array_header_t *child_with_mergeinfo;
7483           svn_client__merge_path_t *target_info;
7484
7485           /* If we have ancestrally related sources and more than one
7486              range to merge, eliminate no-op ranges before going through
7487              the effort of downloading the many copies of the file
7488              required to do these merges (two copies per range). */
7489           if (remaining_ranges->nelts > 1)
7490             {
7491               const char *old_sess_url;
7492               svn_error_t *err;
7493
7494               SVN_ERR(svn_client__ensure_ra_session_url(&old_sess_url,
7495                                                         merge_b->ra_session1,
7496                                                         primary_src->url,
7497                                                         iterpool));
7498               err = remove_noop_merge_ranges(&ranges_to_merge,
7499                                              merge_b->ra_session1,
7500                                              remaining_ranges, scratch_pool);
7501               SVN_ERR(svn_error_compose_create(
7502                         err, svn_ra_reparent(merge_b->ra_session1,
7503                                              old_sess_url, iterpool)));
7504             }
7505
7506           /* To support notify_merge_begin() initialize our
7507              CHILD_WITH_MERGEINFO. See the comment
7508              'THE CHILDREN_WITH_MERGEINFO ARRAY' at the start of this file. */
7509
7510           child_with_mergeinfo = apr_array_make(scratch_pool, 1,
7511                                         sizeof(svn_client__merge_path_t *));
7512
7513           /* ### Create a fake copy of merge_target as we don't keep
7514                  remaining_ranges in sync (yet). */
7515           target_info = apr_pcalloc(scratch_pool, sizeof(*target_info));
7516
7517           target_info->abspath = merge_target->abspath;
7518           target_info->remaining_ranges = ranges_to_merge;
7519
7520           APR_ARRAY_PUSH(child_with_mergeinfo, svn_client__merge_path_t *)
7521                                     = target_info;
7522
7523           /* And store in baton to allow using it from notify_merge_begin() */
7524           merge_b->notify_begin.nodes_with_mergeinfo = child_with_mergeinfo;
7525         }
7526
7527       while (ranges_to_merge->nelts > 0)
7528         {
7529           svn_merge_range_t *r = APR_ARRAY_IDX(ranges_to_merge, 0,
7530                                                svn_merge_range_t *);
7531           const merge_source_t *real_source;
7532           const char *left_file, *right_file;
7533           apr_hash_t *left_props, *right_props;
7534           const svn_diff_source_t *left_source;
7535           const svn_diff_source_t *right_source;
7536
7537           svn_pool_clear(iterpool);
7538
7539           /* Ensure any subsequent drives gets their own notification. */
7540           merge_b->notify_begin.last_abspath = NULL;
7541
7542           /* While we currently don't allow it, in theory we could be
7543              fetching two fulltexts from two different repositories here. */
7544           if (source->ancestral)
7545             real_source = subrange_source(source, r->start, r->end, iterpool);
7546           else
7547             real_source = source;
7548           SVN_ERR(single_file_merge_get_file(&left_file, &left_props,
7549                                              merge_b->ra_session1,
7550                                              real_source->loc1,
7551                                              target_abspath,
7552                                              iterpool, iterpool));
7553           SVN_ERR(single_file_merge_get_file(&right_file, &right_props,
7554                                              merge_b->ra_session2,
7555                                              real_source->loc2,
7556                                              target_abspath,
7557                                              iterpool, iterpool));
7558           /* Calculate sources for the diff processor */
7559           left_source = svn_diff__source_create(r->start, iterpool);
7560           right_source = svn_diff__source_create(r->end, iterpool);
7561
7562
7563           /* If the sources are related or we're ignoring ancestry in diffs,
7564              do a text-n-props merge; otherwise, do a delete-n-add merge. */
7565           if (! (merge_b->diff_ignore_ancestry || sources_related))
7566             {
7567               struct merge_dir_baton_t dir_baton;
7568               void *file_baton;
7569               svn_boolean_t skip;
7570
7571               /* Initialize minimal dir baton to allow calculating 'R'eplace
7572                  from 'D'elete + 'A'dd. */
7573
7574               memset(&dir_baton, 0, sizeof(dir_baton));
7575               dir_baton.pool = iterpool;
7576               dir_baton.tree_conflict_reason = CONFLICT_REASON_NONE;
7577               dir_baton.tree_conflict_action = svn_wc_conflict_action_edit;
7578               dir_baton.skip_reason = svn_wc_notify_state_unknown;
7579
7580               /* Delete... */
7581               file_baton = NULL;
7582               skip = FALSE;
7583               SVN_ERR(processor->file_opened(&file_baton, &skip, target_relpath,
7584                                              left_source,
7585                                              NULL /* right_source */,
7586                                              NULL /* copyfrom_source */,
7587                                              &dir_baton,
7588                                              processor,
7589                                              iterpool, iterpool));
7590               if (! skip)
7591                 SVN_ERR(processor->file_deleted(target_relpath,
7592                                                 left_source,
7593                                                 left_file,
7594                                                 left_props,
7595                                                 file_baton,
7596                                                 processor,
7597                                                 iterpool));
7598
7599               /* ...plus add... */
7600               file_baton = NULL;
7601               skip = FALSE;
7602               SVN_ERR(processor->file_opened(&file_baton, &skip, target_relpath,
7603                                              NULL /* left_source */,
7604                                              right_source,
7605                                              NULL /* copyfrom_source */,
7606                                              &dir_baton,
7607                                              processor,
7608                                              iterpool, iterpool));
7609               if (! skip)
7610                 SVN_ERR(processor->file_added(target_relpath,
7611                                               NULL /* copyfrom_source */,
7612                                               right_source,
7613                                               NULL /* copyfrom_file */,
7614                                               right_file,
7615                                               NULL /* copyfrom_props */,
7616                                               right_props,
7617                                               file_baton,
7618                                               processor,
7619                                               iterpool));
7620               /* ... equals replace. */
7621             }
7622           else
7623             {
7624               void *file_baton = NULL;
7625               svn_boolean_t skip = FALSE;
7626               apr_array_header_t *propchanges;
7627
7628
7629               /* Deduce property diffs. */
7630               SVN_ERR(svn_prop_diffs(&propchanges, right_props, left_props,
7631                                      iterpool));
7632
7633               SVN_ERR(processor->file_opened(&file_baton, &skip, target_relpath,
7634                                              left_source,
7635                                              right_source,
7636                                              NULL /* copyfrom_source */,
7637                                              NULL /* dir_baton */,
7638                                              processor,
7639                                              iterpool, iterpool));
7640               if (! skip)
7641                 SVN_ERR(processor->file_changed(target_relpath,
7642                                               left_source,
7643                                               right_source,
7644                                               left_file,
7645                                               right_file,
7646                                               left_props,
7647                                               right_props,
7648                                               TRUE /* file changed */,
7649                                               propchanges,
7650                                               file_baton,
7651                                               processor,
7652                                               iterpool));
7653             }
7654
7655           if (is_path_conflicted_by_merge(merge_b))
7656             {
7657               merge_source_t *remaining_range = NULL;
7658
7659               if (real_source->loc2->rev != source->loc2->rev)
7660                 remaining_range = subrange_source(source,
7661                                                   real_source->loc2->rev,
7662                                                   source->loc2->rev,
7663                                                   scratch_pool);
7664               *conflict_report = single_range_conflict_report_create(
7665                                    real_source, remaining_range, result_pool);
7666
7667               /* Only record partial mergeinfo if only a partial merge was
7668                  performed before a conflict was encountered. */
7669               range.end = r->end;
7670               break;
7671             }
7672
7673           /* Now delete the just merged range from the hash
7674              (This list is used from notify_merge_begin)
7675
7676             Directory merges use remove_first_range_from_remaining_ranges() */
7677           svn_sort__array_delete(ranges_to_merge, 0, 1);
7678         }
7679       merge_b->notify_begin.last_abspath = NULL;
7680     } /* !merge_b->record_only */
7681
7682   /* Record updated WC mergeinfo to account for our new merges, minus
7683      any unresolved conflicts and skips.  We use the original
7684      REMAINING_RANGES here because we want to record all the requested
7685      merge ranges, include the noop ones.  */
7686   if (RECORD_MERGEINFO(merge_b) && remaining_ranges->nelts)
7687     {
7688       const char *mergeinfo_path = svn_client__pathrev_fspath(primary_src,
7689                                                               scratch_pool);
7690       svn_rangelist_t *filtered_rangelist;
7691
7692       /* Filter any ranges from TARGET_WCPATH's own history, there is no
7693          need to record this explicitly in mergeinfo, it is already part
7694          of TARGET_WCPATH's natural history (implicit mergeinfo). */
7695       SVN_ERR(filter_natural_history_from_mergeinfo(
7696         &filtered_rangelist,
7697         mergeinfo_path,
7698         merge_target->implicit_mergeinfo,
7699         &range,
7700         iterpool));
7701
7702       /* Only record mergeinfo if there is something other than
7703          self-referential mergeinfo, but don't record mergeinfo if
7704          TARGET_WCPATH was skipped. */
7705       if (filtered_rangelist->nelts
7706           && (apr_hash_count(merge_b->skipped_abspaths) == 0))
7707         {
7708           apr_hash_t *merges = apr_hash_make(iterpool);
7709
7710           /* If merge target has inherited mergeinfo set it before
7711              recording the first merge range. */
7712           if (inherited)
7713             SVN_ERR(svn_client__record_wc_mergeinfo(target_abspath,
7714                                                     target_mergeinfo,
7715                                                     FALSE, ctx,
7716                                                     iterpool));
7717
7718           svn_hash_sets(merges, target_abspath, filtered_rangelist);
7719
7720           if (!squelch_mergeinfo_notifications)
7721             {
7722               /* Notify that we are recording mergeinfo describing a merge. */
7723               svn_merge_range_t n_range;
7724
7725               SVN_ERR(svn_mergeinfo__get_range_endpoints(
7726                         &n_range.end, &n_range.start, merges, iterpool));
7727               n_range.inheritable = TRUE;
7728               notify_mergeinfo_recording(target_abspath, &n_range,
7729                                          merge_b->ctx, iterpool);
7730             }
7731
7732           SVN_ERR(update_wc_mergeinfo(result_catalog, target_abspath,
7733                                       mergeinfo_path, merges, is_rollback,
7734                                       ctx, iterpool));
7735         }
7736     }
7737
7738   merge_b->notify_begin.nodes_with_mergeinfo = NULL;
7739
7740   svn_pool_destroy(iterpool);
7741
7742   return SVN_NO_ERROR;
7743 }
7744
7745 /* Helper for do_directory_merge() to handle the case where a merge editor
7746    drive adds explicit mergeinfo to a path which didn't have any explicit
7747    mergeinfo previously.
7748
7749    MERGE_B is cascaded from the argument of the same
7750    name in do_directory_merge().  Should be called only after
7751    do_directory_merge() has called populate_remaining_ranges() and populated
7752    the remaining_ranges field of each child in
7753    CHILDREN_WITH_MERGEINFO (i.e. the remaining_ranges fields can be
7754    empty but never NULL).
7755
7756    If MERGE_B->DRY_RUN is true do nothing, if it is false then
7757    for each path (if any) in MERGE_B->PATHS_WITH_NEW_MERGEINFO merge that
7758    path's inherited mergeinfo (if any) with its working explicit mergeinfo
7759    and set that as the path's new explicit mergeinfo.  Then add an
7760    svn_client__merge_path_t * element representing the path to
7761    CHILDREN_WITH_MERGEINFO if it isn't already present.  All fields
7762    in any elements added to CHILDREN_WITH_MERGEINFO are initialized
7763    to FALSE/NULL with the exception of 'path' and 'remaining_ranges'.  The
7764    latter is set to a rangelist equal to the remaining_ranges of the path's
7765    nearest path-wise ancestor in CHILDREN_WITH_MERGEINFO.
7766
7767    Any elements added to CHILDREN_WITH_MERGEINFO are allocated
7768    in POOL. */
7769 static svn_error_t *
7770 process_children_with_new_mergeinfo(merge_cmd_baton_t *merge_b,
7771                                     apr_array_header_t *children_with_mergeinfo,
7772                                     apr_pool_t *pool)
7773 {
7774   apr_pool_t *iterpool;
7775   apr_hash_index_t *hi;
7776
7777   if (!merge_b->paths_with_new_mergeinfo || merge_b->dry_run)
7778     return SVN_NO_ERROR;
7779
7780   /* Iterate over each path with explicit mergeinfo added by the merge. */
7781   iterpool = svn_pool_create(pool);
7782   for (hi = apr_hash_first(pool, merge_b->paths_with_new_mergeinfo);
7783        hi;
7784        hi = apr_hash_next(hi))
7785     {
7786       const char *abspath_with_new_mergeinfo = svn__apr_hash_index_key(hi);
7787       svn_mergeinfo_t path_inherited_mergeinfo;
7788       svn_mergeinfo_t path_explicit_mergeinfo;
7789       svn_client__merge_path_t *new_child;
7790
7791       svn_pool_clear(iterpool);
7792
7793       /* Note: We could skip recording inherited mergeinfo here if this path
7794          was added (with preexisting mergeinfo) by the merge.  That's actually
7795          more correct, since the inherited mergeinfo likely describes
7796          non-existent or unrelated merge history, but it's not quite so simple
7797          as that, see http://subversion.tigris.org/issues/show_bug.cgi?id=4309
7798          */
7799
7800       /* Get the path's new explicit mergeinfo... */
7801       SVN_ERR(svn_client__get_wc_mergeinfo(&path_explicit_mergeinfo, NULL,
7802                                            svn_mergeinfo_explicit,
7803                                            abspath_with_new_mergeinfo,
7804                                            NULL, NULL, FALSE,
7805                                            merge_b->ctx,
7806                                            iterpool, iterpool));
7807       /* ...there *should* always be explicit mergeinfo at this point
7808          but you can't be too careful. */
7809       if (path_explicit_mergeinfo)
7810         {
7811           /* Get the mergeinfo the path would have inherited before
7812              the merge. */
7813           SVN_ERR(svn_client__get_wc_or_repos_mergeinfo(
7814             &path_inherited_mergeinfo,
7815             NULL, NULL,
7816             FALSE,
7817             svn_mergeinfo_nearest_ancestor, /* We only want inherited MI */
7818             merge_b->ra_session2,
7819             abspath_with_new_mergeinfo,
7820             merge_b->ctx,
7821             iterpool));
7822
7823           /* If the path inherited any mergeinfo then merge that with the
7824              explicit mergeinfo and record the result as the path's new
7825              explicit mergeinfo. */
7826           if (path_inherited_mergeinfo)
7827             {
7828               SVN_ERR(svn_mergeinfo_merge2(path_explicit_mergeinfo,
7829                                            path_inherited_mergeinfo,
7830                                            iterpool, iterpool));
7831               SVN_ERR(svn_client__record_wc_mergeinfo(
7832                                           abspath_with_new_mergeinfo,
7833                                           path_explicit_mergeinfo,
7834                                           FALSE, merge_b->ctx, iterpool));
7835             }
7836
7837           /* If the path is not in CHILDREN_WITH_MERGEINFO then add it. */
7838           new_child =
7839             get_child_with_mergeinfo(children_with_mergeinfo,
7840                                      abspath_with_new_mergeinfo);
7841           if (!new_child)
7842             {
7843               const svn_client__merge_path_t *parent
7844                 = find_nearest_ancestor(children_with_mergeinfo,
7845                                         FALSE, abspath_with_new_mergeinfo);
7846               new_child
7847                 = svn_client__merge_path_create(abspath_with_new_mergeinfo,
7848                                                 pool);
7849
7850               /* If path_with_new_mergeinfo is the merge target itself
7851                  then it should already be in
7852                  CHILDREN_WITH_MERGEINFO per the criteria of
7853                  get_mergeinfo_paths() and we shouldn't be in this block.
7854                  If path_with_new_mergeinfo is a subtree then it must have
7855                  a parent in CHILDREN_WITH_MERGEINFO if only
7856                  the merge target itself...so if we don't find a parent
7857                  the caller has done something quite wrong. */
7858               SVN_ERR_ASSERT(parent);
7859               SVN_ERR_ASSERT(parent->remaining_ranges);
7860
7861               /* Set the path's remaining_ranges equal to its parent's. */
7862               new_child->remaining_ranges = svn_rangelist_dup(
7863                  parent->remaining_ranges, pool);
7864               insert_child_to_merge(children_with_mergeinfo, new_child, pool);
7865             }
7866         }
7867     }
7868   svn_pool_destroy(iterpool);
7869
7870   return SVN_NO_ERROR;
7871 }
7872
7873 /* Return true if any path in SUBTREES is equal to, or is a subtree of,
7874    LOCAL_ABSPATH.  Return false otherwise.  The keys of SUBTREES are
7875    (const char *) absolute paths and its values are irrelevant.
7876    If SUBTREES is NULL return false. */
7877 static svn_boolean_t
7878 path_is_subtree(const char *local_abspath,
7879                 apr_hash_t *subtrees,
7880                 apr_pool_t *pool)
7881 {
7882   if (subtrees)
7883     {
7884       apr_hash_index_t *hi;
7885
7886       for (hi = apr_hash_first(pool, subtrees);
7887            hi; hi = apr_hash_next(hi))
7888         {
7889           const char *path_touched_by_merge = svn__apr_hash_index_key(hi);
7890           if (svn_dirent_is_ancestor(local_abspath, path_touched_by_merge))
7891             return TRUE;
7892         }
7893     }
7894   return FALSE;
7895 }
7896
7897 /* Return true if any merged, skipped, added or tree-conflicted path
7898    recorded in MERGE_B is equal to, or is a subtree of LOCAL_ABSPATH.  Return
7899    false otherwise.
7900
7901    ### Why not text- or prop-conflicted paths? Are such paths guaranteed
7902        to be recorded as 'merged' or 'skipped' or 'added', perhaps?
7903 */
7904 static svn_boolean_t
7905 subtree_touched_by_merge(const char *local_abspath,
7906                          merge_cmd_baton_t *merge_b,
7907                          apr_pool_t *pool)
7908 {
7909   return (path_is_subtree(local_abspath, merge_b->merged_abspaths, pool)
7910           || path_is_subtree(local_abspath, merge_b->skipped_abspaths, pool)
7911           || path_is_subtree(local_abspath, merge_b->added_abspaths, pool)
7912           || path_is_subtree(local_abspath, merge_b->tree_conflicted_abspaths,
7913                              pool));
7914 }
7915
7916 /* Helper for do_directory_merge() when performing mergeinfo unaware merges.
7917
7918    Merge the SOURCE diff into TARGET_DIR_WCPATH.
7919
7920    SOURCE, DEPTH, NOTIFY_B, and MERGE_B
7921    are all cascaded from do_directory_merge's arguments of the same names.
7922
7923    CONFLICT_REPORT is as documented for do_directory_merge().
7924
7925    NOTE: This is a very thin wrapper around drive_merge_report_editor() and
7926    exists only to populate CHILDREN_WITH_MERGEINFO with the single element
7927    expected during mergeinfo unaware merges.
7928 */
7929 static svn_error_t *
7930 do_mergeinfo_unaware_dir_merge(single_range_conflict_report_t **conflict_report,
7931                                const merge_source_t *source,
7932                                const char *target_dir_wcpath,
7933                                apr_array_header_t *children_with_mergeinfo,
7934                                const svn_diff_tree_processor_t *processor,
7935                                svn_depth_t depth,
7936                                merge_cmd_baton_t *merge_b,
7937                                apr_pool_t *result_pool,
7938                                apr_pool_t *scratch_pool)
7939 {
7940   /* Initialize CHILDREN_WITH_MERGEINFO and populate it with
7941      one element describing the merge of SOURCE->rev1:rev2 to
7942      TARGET_DIR_WCPATH. */
7943   svn_client__merge_path_t *item
7944     = svn_client__merge_path_create(target_dir_wcpath, scratch_pool);
7945
7946   *conflict_report = NULL;
7947   item->remaining_ranges = svn_rangelist__initialize(source->loc1->rev,
7948                                                      source->loc2->rev,
7949                                                      TRUE, scratch_pool);
7950   APR_ARRAY_PUSH(children_with_mergeinfo,
7951                  svn_client__merge_path_t *) = item;
7952   SVN_ERR(drive_merge_report_editor(target_dir_wcpath,
7953                                     source,
7954                                     NULL, processor, depth,
7955                                     merge_b, scratch_pool));
7956   if (is_path_conflicted_by_merge(merge_b))
7957     {
7958       *conflict_report = single_range_conflict_report_create(
7959                            source, NULL, result_pool);
7960     }
7961   return SVN_NO_ERROR;
7962 }
7963
7964 /* A svn_log_entry_receiver_t baton for log_find_operative_subtree_revs(). */
7965 typedef struct log_find_operative_subtree_baton_t
7966 {
7967   /* Mapping of const char * absolute working copy paths to those
7968      path's const char * repos absolute paths. */
7969   apr_hash_t *operative_children;
7970
7971   /* As per the arguments of the same name to
7972      get_operative_immediate_children(). */
7973   const char *merge_source_fspath;
7974   const char *merge_target_abspath;
7975   svn_depth_t depth;
7976   svn_wc_context_t *wc_ctx;
7977
7978   /* A pool to allocate additions to the hashes in. */
7979   apr_pool_t *result_pool;
7980 } log_find_operative_subtree_baton_t;
7981
7982 /* A svn_log_entry_receiver_t callback for
7983    get_inoperative_immediate_children(). */
7984 static svn_error_t *
7985 log_find_operative_subtree_revs(void *baton,
7986                                 svn_log_entry_t *log_entry,
7987                                 apr_pool_t *pool)
7988 {
7989   log_find_operative_subtree_baton_t *log_baton = baton;
7990   apr_hash_index_t *hi;
7991   apr_pool_t *iterpool;
7992
7993   /* It's possible that authz restrictions on the merge source prevent us
7994      from knowing about any of the changes for LOG_ENTRY->REVISION. */
7995   if (!log_entry->changed_paths2)
7996     return SVN_NO_ERROR;
7997
7998   iterpool = svn_pool_create(pool);
7999
8000   for (hi = apr_hash_first(pool, log_entry->changed_paths2);
8001        hi;
8002        hi = apr_hash_next(hi))
8003     {
8004       const char *path = svn__apr_hash_index_key(hi);
8005       svn_log_changed_path2_t *change = svn__apr_hash_index_val(hi);
8006
8007         {
8008           const char *child;
8009           const char *potential_child;
8010           const char *rel_path =
8011             svn_fspath__skip_ancestor(log_baton->merge_source_fspath, path);
8012
8013           /* Some affected paths might be the root of the merge source or
8014              entirely outside our subtree of interest. In either case they
8015              are not operative *immediate* children. */
8016           if (rel_path == NULL
8017               || rel_path[0] == '\0')
8018             continue;
8019
8020           svn_pool_clear(iterpool);
8021
8022           child = svn_relpath_dirname(rel_path, iterpool);
8023           if (child[0] == '\0')
8024             {
8025               /* The svn_log_changed_path2_t.node_kind members in
8026                  LOG_ENTRY->CHANGED_PATHS2 may be set to
8027                  svn_node_unknown, see svn_log_changed_path2_t and
8028                  svn_fs_paths_changed2.  In that case we check the
8029                  type of the corresponding subtree in the merge
8030                  target. */
8031               svn_node_kind_t node_kind;
8032
8033               if (change->node_kind == svn_node_unknown)
8034                 {
8035                   const char *wc_child_abspath =
8036                     svn_dirent_join(log_baton->merge_target_abspath,
8037                                     rel_path, iterpool);
8038
8039                   SVN_ERR(svn_wc_read_kind2(&node_kind, log_baton->wc_ctx,
8040                                             wc_child_abspath, FALSE, FALSE,
8041                                             iterpool));
8042                 }
8043               else
8044                 {
8045                   node_kind = change->node_kind;
8046                 }
8047
8048               /* We only care about immediate directory children if
8049                  DEPTH is svn_depth_files. */
8050               if (log_baton->depth == svn_depth_files
8051                   && node_kind != svn_node_dir)
8052                 continue;
8053
8054               /* If depth is svn_depth_immediates, then we only care
8055                  about changes to proper subtrees of PATH.  If the change
8056                  is to PATH itself then PATH is within the operational
8057                  depth of the merge. */
8058               if (log_baton->depth == svn_depth_immediates)
8059                 continue;
8060
8061               child = rel_path;
8062             }
8063
8064           potential_child = svn_dirent_join(log_baton->merge_target_abspath,
8065                                             child, iterpool);
8066
8067           if (change->action == 'A'
8068               || !svn_hash_gets(log_baton->operative_children,
8069                                 potential_child))
8070             {
8071               svn_hash_sets(log_baton->operative_children,
8072                             apr_pstrdup(log_baton->result_pool,
8073                                         potential_child),
8074                             apr_pstrdup(log_baton->result_pool, path));
8075             }
8076         }
8077     }
8078   svn_pool_destroy(iterpool);
8079   return SVN_NO_ERROR;
8080 }
8081
8082 /* Find immediate subtrees of MERGE_TARGET_ABSPATH which would have
8083    additional differences applied if record_mergeinfo_for_dir_merge() were
8084    recording mergeinfo describing a merge at svn_depth_infinity, rather
8085    than at DEPTH (which is assumed to be shallow; if
8086    DEPTH == svn_depth_infinity then this function does nothing beyond
8087    setting *OPERATIVE_CHILDREN to an empty hash).
8088
8089    MERGE_SOURCE_FSPATH is the absolute repository path of the merge
8090    source.  OLDEST_REV and YOUNGEST_REV are the revisions merged from
8091    MERGE_SOURCE_FSPATH to MERGE_TARGET_ABSPATH.
8092
8093    RA_SESSION points to MERGE_SOURCE_FSPATH.
8094
8095    Set *OPERATIVE_CHILDREN to a hash (mapping const char * absolute
8096    working copy paths to those path's const char * repos absolute paths)
8097    containing all the immediate subtrees of MERGE_TARGET_ABSPATH which would
8098    have a different diff applied if MERGE_SOURCE_FSPATH
8099    -r(OLDEST_REV - 1):YOUNGEST_REV were merged to MERGE_TARGET_ABSPATH at
8100    svn_depth_infinity rather than DEPTH.
8101
8102    RESULT_POOL is used to allocate the contents of *OPERATIVE_CHILDREN.
8103    SCRATCH_POOL is used for temporary allocations. */
8104 static svn_error_t *
8105 get_operative_immediate_children(apr_hash_t **operative_children,
8106                                  const char *merge_source_fspath,
8107                                  svn_revnum_t oldest_rev,
8108                                  svn_revnum_t youngest_rev,
8109                                  const char *merge_target_abspath,
8110                                  svn_depth_t depth,
8111                                  svn_wc_context_t *wc_ctx,
8112                                  svn_ra_session_t *ra_session,
8113                                  apr_pool_t *result_pool,
8114                                  apr_pool_t *scratch_pool)
8115 {
8116   log_find_operative_subtree_baton_t log_baton;
8117
8118   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(oldest_rev));
8119   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
8120   SVN_ERR_ASSERT(oldest_rev <= youngest_rev);
8121
8122   *operative_children = apr_hash_make(result_pool);
8123
8124   if (depth == svn_depth_infinity)
8125     return SVN_NO_ERROR;
8126
8127   /* Now remove any paths from *OPERATIVE_CHILDREN that are inoperative when
8128      merging MERGE_SOURCE_REPOS_PATH -r(OLDEST_REV - 1):YOUNGEST_REV to
8129      MERGE_TARGET_ABSPATH at --depth infinity. */
8130   log_baton.operative_children = *operative_children;
8131   log_baton.merge_source_fspath = merge_source_fspath;
8132   log_baton.merge_target_abspath = merge_target_abspath;
8133   log_baton.depth = depth;
8134   log_baton.wc_ctx = wc_ctx;
8135   log_baton.result_pool = result_pool;
8136
8137   SVN_ERR(get_log(ra_session, "", youngest_rev, oldest_rev,
8138                   TRUE, /* discover_changed_paths */
8139                   log_find_operative_subtree_revs,
8140                   &log_baton, scratch_pool));
8141
8142   return SVN_NO_ERROR;
8143 }
8144
8145 /* Helper for record_mergeinfo_for_dir_merge(): Identify which elements of
8146    CHILDREN_WITH_MERGEINFO need new mergeinfo set to accurately
8147    describe a merge, what inheritance type such new mergeinfo should have,
8148    and what subtrees can be ignored altogether.
8149
8150    For each svn_client__merge_path_t CHILD in CHILDREN_WITH_MERGEINFO,
8151    set CHILD->RECORD_MERGEINFO and CHILD->RECORD_NONINHERITABLE to true
8152    if the subtree needs mergeinfo to describe the merge and if that
8153    mergeinfo should be non-inheritable respectively.
8154
8155    If OPERATIVE_MERGE is true, then the merge being described is operative
8156    as per subtree_touched_by_merge().  OPERATIVE_MERGE is false otherwise.
8157
8158    MERGED_RANGE, MERGEINFO_FSPATH, DEPTH, NOTIFY_B, and MERGE_B are all
8159    cascaded from record_mergeinfo_for_dir_merge's arguments of the same
8160    names.
8161
8162    SCRATCH_POOL is used for temporary allocations.
8163 */
8164 static svn_error_t *
8165 flag_subtrees_needing_mergeinfo(svn_boolean_t operative_merge,
8166                                 const svn_merge_range_t *merged_range,
8167                                 apr_array_header_t *children_with_mergeinfo,
8168                                 const char *mergeinfo_fspath,
8169                                 svn_depth_t depth,
8170                                 merge_cmd_baton_t *merge_b,
8171                                 apr_pool_t *scratch_pool)
8172 {
8173   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
8174   int i;
8175   apr_hash_t *operative_immediate_children = NULL;
8176
8177   assert(! merge_b->dry_run);
8178
8179   if (!merge_b->record_only
8180       && merged_range->start <= merged_range->end
8181       && (depth < svn_depth_infinity))
8182     SVN_ERR(get_operative_immediate_children(
8183       &operative_immediate_children,
8184       mergeinfo_fspath, merged_range->start + 1, merged_range->end,
8185       merge_b->target->abspath, depth, merge_b->ctx->wc_ctx,
8186       merge_b->ra_session1, scratch_pool, iterpool));
8187
8188   /* Issue #4056: Walk NOTIFY_B->CHILDREN_WITH_MERGEINFO reverse depth-first
8189      order.  This way each child knows if it has operative missing/switched
8190      children which necessitates non-inheritable mergeinfo. */
8191   for (i = children_with_mergeinfo->nelts - 1; i >= 0; i--)
8192     {
8193       svn_client__merge_path_t *child =
8194                      APR_ARRAY_IDX(children_with_mergeinfo, i,
8195                                    svn_client__merge_path_t *);
8196
8197       /* Can't record mergeinfo on something that isn't here. */
8198       if (child->absent)
8199         continue;
8200
8201       /* Verify that remove_children_with_deleted_mergeinfo() did its job */
8202       assert((i == 0)
8203              ||! merge_b->paths_with_deleted_mergeinfo
8204              || !svn_hash_gets(merge_b->paths_with_deleted_mergeinfo,
8205                                child->abspath));
8206
8207       /* Don't record mergeinfo on skipped paths. */
8208       if (svn_hash_gets(merge_b->skipped_abspaths, child->abspath))
8209         continue;
8210
8211       /* ### ptb: Yes, we could combine the following into a single
8212          ### conditional, but clarity would suffer (even more than
8213          ### it does now). */
8214       if (i == 0)
8215         {
8216           /* Always record mergeinfo on the merge target. */
8217           child->record_mergeinfo = TRUE;
8218         }
8219       else if (merge_b->record_only && !merge_b->reintegrate_merge)
8220         {
8221           /* Always record mergeinfo for --record-only merges. */
8222           child->record_mergeinfo = TRUE;
8223         }
8224       else if (child->immediate_child_dir
8225                && !child->pre_merge_mergeinfo
8226                && operative_immediate_children
8227                && svn_hash_gets(operative_immediate_children, child->abspath))
8228         {
8229           /* We must record mergeinfo on those issue #3642 children
8230              that are operative at a greater depth. */
8231           child->record_mergeinfo = TRUE;
8232         }
8233
8234       if (operative_merge
8235           && subtree_touched_by_merge(child->abspath, merge_b, iterpool))
8236         {
8237           svn_pool_clear(iterpool);
8238
8239           /* This subtree was affected by the merge. */
8240           child->record_mergeinfo = TRUE;
8241
8242           /* Were any CHILD's missing children skipped by the merge?
8243              If not, then CHILD's missing children don't need to be
8244              considered when recording mergeinfo describing the merge. */
8245           if (! merge_b->reintegrate_merge
8246               && child->missing_child
8247               && !path_is_subtree(child->abspath,
8248                                   merge_b->skipped_abspaths,
8249                                   iterpool))
8250             {
8251               child->missing_child = FALSE;
8252             }
8253
8254           /* If CHILD has an immediate switched child or children and
8255              none of these were touched by the merge, then we don't need
8256              need to do any special handling of those switched subtrees
8257              (e.g. record non-inheritable mergeinfo) when recording
8258              mergeinfo describing the merge. */
8259           if (child->switched_child)
8260             {
8261               int j;
8262               svn_boolean_t operative_switched_child = FALSE;
8263
8264               for (j = i + 1;
8265                    j < children_with_mergeinfo->nelts;
8266                    j++)
8267                 {
8268                   svn_client__merge_path_t *potential_child =
8269                     APR_ARRAY_IDX(children_with_mergeinfo, j,
8270                                   svn_client__merge_path_t *);
8271                   if (!svn_dirent_is_ancestor(child->abspath,
8272                                               potential_child->abspath))
8273                     break;
8274
8275                   /* POTENTIAL_CHILD is a subtree of CHILD, but is it
8276                      an immediate child? */
8277                   if (strcmp(child->abspath,
8278                              svn_dirent_dirname(potential_child->abspath,
8279                                                 iterpool)))
8280                     continue;
8281
8282                   if (potential_child->switched
8283                       && potential_child->record_mergeinfo)
8284                     {
8285                       operative_switched_child = TRUE;
8286                       break;
8287                     }
8288                 }
8289
8290               /* Can we treat CHILD as if it has no switched children? */
8291               if (! operative_switched_child)
8292                 child->switched_child = FALSE;
8293             }
8294         }
8295
8296       if (child->record_mergeinfo)
8297         {
8298           /* We need to record mergeinfo, but should that mergeinfo be
8299              non-inheritable? */
8300           svn_node_kind_t path_kind;
8301           SVN_ERR(svn_wc_read_kind2(&path_kind, merge_b->ctx->wc_ctx,
8302                                     child->abspath, FALSE, FALSE, iterpool));
8303
8304           /* Only directories can have non-inheritable mergeinfo. */
8305           if (path_kind == svn_node_dir)
8306             {
8307               /* There are two general cases where non-inheritable mergeinfo
8308                  is required:
8309
8310                  1) There merge target has missing subtrees (due to authz
8311                     restrictions, switched subtrees, or a shallow working
8312                     copy).
8313
8314                  2) The operational depth of the merge itself is shallow. */
8315
8316               /* We've already determined the first case. */
8317               child->record_noninheritable =
8318                 child->missing_child || child->switched_child;
8319
8320               /* The second case requires a bit more work. */
8321               if (i == 0)
8322                 {
8323                   /* If CHILD is the root of the merge target and the
8324                      operational depth is empty or files, then the mere
8325                      existence of operative immediate children means we
8326                      must record non-inheritable mergeinfo.
8327
8328                      ### What about svn_depth_immediates?  In that case
8329                      ### the merge target needs only normal inheritable
8330                      ### mergeinfo and the target's immediate children will
8331                      ### get non-inheritable mergeinfo, assuming they
8332                      ### need even that. */
8333                   if (depth < svn_depth_immediates
8334                       && operative_immediate_children
8335                       && apr_hash_count(operative_immediate_children))
8336                     child->record_noninheritable = TRUE;
8337                 }
8338               else if (depth == svn_depth_immediates)
8339                 {
8340                   /* An immediate directory child of the merge target, which
8341                       was affected by a --depth=immediates merge, needs
8342                       non-inheritable mergeinfo. */
8343                   if (svn_hash_gets(operative_immediate_children,
8344                                     child->abspath))
8345                     child->record_noninheritable = TRUE;
8346                 }
8347             }
8348         }
8349       else /* child->record_mergeinfo */
8350         {
8351           /* If CHILD is in NOTIFY_B->CHILDREN_WITH_MERGEINFO simply
8352              because it had no explicit mergeinfo of its own at the
8353              start of the merge but is the child of of some path with
8354              non-inheritable mergeinfo, then the explicit mergeinfo it
8355              has *now* was set by get_mergeinfo_paths() -- see criteria
8356              3 in that function's doc string.  So since CHILD->ABSPATH
8357              was not touched by the merge we can remove the
8358              mergeinfo. */
8359           if (child->child_of_noninheritable)
8360             SVN_ERR(svn_client__record_wc_mergeinfo(child->abspath,
8361                                                     NULL, FALSE,
8362                                                     merge_b->ctx,
8363                                                     iterpool));
8364         }
8365     }
8366
8367   svn_pool_destroy(iterpool);
8368   return SVN_NO_ERROR;
8369 }
8370
8371 /* Helper for do_directory_merge().
8372
8373    If RESULT_CATALOG is NULL then record mergeinfo describing a merge of
8374    MERGED_RANGE->START:MERGED_RANGE->END from the repository relative path
8375    MERGEINFO_FSPATH to the merge target (and possibly its subtrees) described
8376    by NOTIFY_B->CHILDREN_WITH_MERGEINFO -- see the global comment
8377    'THE CHILDREN_WITH_MERGEINFO ARRAY'.  Obviously this should only
8378    be called if recording mergeinfo -- see doc string for RECORD_MERGEINFO().
8379
8380    If RESULT_CATALOG is not NULL, then don't record the new mergeinfo on the
8381    WC, but instead record it in RESULT_CATALOG, where the keys are absolute
8382    working copy paths and the values are the new mergeinfos for each.
8383    Allocate additions to RESULT_CATALOG in pool which RESULT_CATALOG was
8384    created in.
8385
8386    DEPTH, NOTIFY_B, MERGE_B, and SQUELCH_MERGEINFO_NOTIFICATIONS are all
8387    cascaded from do_directory_merge's arguments of the same names.
8388
8389    SCRATCH_POOL is used for temporary allocations.
8390 */
8391 static svn_error_t *
8392 record_mergeinfo_for_dir_merge(svn_mergeinfo_catalog_t result_catalog,
8393                                const svn_merge_range_t *merged_range,
8394                                const char *mergeinfo_fspath,
8395                                apr_array_header_t *children_with_mergeinfo,
8396                                svn_depth_t depth,
8397                                svn_boolean_t squelch_mergeinfo_notifications,
8398                                merge_cmd_baton_t *merge_b,
8399                                apr_pool_t *scratch_pool)
8400 {
8401   int i;
8402   svn_boolean_t is_rollback = (merged_range->start > merged_range->end);
8403   svn_boolean_t operative_merge;
8404
8405   /* Update the WC mergeinfo here to account for our new
8406      merges, minus any unresolved conflicts and skips. */
8407
8408   /* We need a scratch pool for iterations below. */
8409   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
8410
8411   svn_merge_range_t range = *merged_range;
8412
8413   assert(! merge_b->dry_run);
8414
8415   /* Regardless of what subtrees in MERGE_B->target->abspath might be missing
8416      could this merge have been operative? */
8417   operative_merge = subtree_touched_by_merge(merge_b->target->abspath,
8418                                              merge_b, iterpool);
8419
8420   /* If this couldn't be an operative merge then don't bother with
8421      the added complexity (and user confusion) of non-inheritable ranges.
8422      There is no harm in subtrees inheriting inoperative mergeinfo. */
8423   if (!operative_merge)
8424     range.inheritable = TRUE;
8425
8426   /* Remove absent children at or under MERGE_B->target->abspath from
8427      NOTIFY_B->CHILDREN_WITH_MERGEINFO
8428      before we calculate the merges performed. */
8429   remove_absent_children(merge_b->target->abspath,
8430                          children_with_mergeinfo);
8431
8432   /* Determine which subtrees of interest need mergeinfo recorded... */
8433   SVN_ERR(flag_subtrees_needing_mergeinfo(operative_merge, &range,
8434                                           children_with_mergeinfo,
8435                                           mergeinfo_fspath, depth,
8436                                           merge_b, iterpool));
8437
8438   /* ...and then record it. */
8439   for (i = 0; i < children_with_mergeinfo->nelts; i++)
8440     {
8441       const char *child_repos_path;
8442       const char *child_merge_src_fspath;
8443       svn_rangelist_t *child_merge_rangelist;
8444       apr_hash_t *child_merges;
8445       svn_client__merge_path_t *child =
8446                      APR_ARRAY_IDX(children_with_mergeinfo, i,
8447                                    svn_client__merge_path_t *);
8448       SVN_ERR_ASSERT(child);
8449
8450       svn_pool_clear(iterpool);
8451
8452       if (child->record_mergeinfo)
8453         {
8454           child_repos_path = svn_dirent_skip_ancestor(merge_b->target->abspath,
8455                                                       child->abspath);
8456           SVN_ERR_ASSERT(child_repos_path != NULL);
8457           child_merge_src_fspath = svn_fspath__join(mergeinfo_fspath,
8458                                                     child_repos_path,
8459                                                     iterpool);
8460           /* Filter any ranges from each child's natural history before
8461              setting mergeinfo describing the merge. */
8462           SVN_ERR(filter_natural_history_from_mergeinfo(
8463             &child_merge_rangelist, child_merge_src_fspath,
8464             child->implicit_mergeinfo, &range, iterpool));
8465
8466           if (child_merge_rangelist->nelts == 0)
8467             continue;
8468
8469           if (!squelch_mergeinfo_notifications)
8470             {
8471               /* If the merge source has a gap, then don't mention
8472                  those gap revisions in the notification. */
8473               remove_source_gap(&range, merge_b->implicit_src_gap);
8474               notify_mergeinfo_recording(child->abspath, &range,
8475                                          merge_b->ctx, iterpool);
8476             }
8477
8478           /* If we are here we know we will be recording some mergeinfo, but
8479              before we do, set override mergeinfo on skipped paths so they
8480              don't incorrectly inherit the mergeinfo we are about to set. */
8481           if (i == 0)
8482             SVN_ERR(record_skips_in_mergeinfo(mergeinfo_fspath,
8483                                               child_merge_rangelist,
8484                                               is_rollback, merge_b, iterpool));
8485
8486           /* We may need to record non-inheritable mergeinfo that applies
8487              only to CHILD->ABSPATH. */
8488           if (child->record_noninheritable)
8489             svn_rangelist__set_inheritance(child_merge_rangelist, FALSE);
8490
8491           /* If CHILD has inherited mergeinfo set it before
8492              recording the first merge range. */
8493           if (child->inherited_mergeinfo)
8494             SVN_ERR(svn_client__record_wc_mergeinfo(
8495               child->abspath,
8496               child->pre_merge_mergeinfo,
8497               FALSE, merge_b->ctx,
8498               iterpool));
8499           if (merge_b->implicit_src_gap)
8500             {
8501               /* If this is a reverse merge reorder CHILD->REMAINING_RANGES
8502                  so it will work with the svn_rangelist_remove API. */
8503               if (is_rollback)
8504                 SVN_ERR(svn_rangelist_reverse(child_merge_rangelist,
8505                                               iterpool));
8506
8507               SVN_ERR(svn_rangelist_remove(&child_merge_rangelist,
8508                                            merge_b->implicit_src_gap,
8509                                            child_merge_rangelist, FALSE,
8510                                            iterpool));
8511               if (is_rollback)
8512                 SVN_ERR(svn_rangelist_reverse(child_merge_rangelist,
8513                                               iterpool));
8514             }
8515
8516           child_merges = apr_hash_make(iterpool);
8517
8518           /* The short story:
8519
8520              If we are describing a forward merge, then the naive mergeinfo
8521              defined by MERGE_SOURCE_PATH:MERGED_RANGE->START:
8522              MERGE_SOURCE_PATH:MERGED_RANGE->END may contain non-existent
8523              path-revs or may describe other lines of history.  We must
8524              remove these invalid portion(s) before recording mergeinfo
8525              describing the merge.
8526
8527              The long story:
8528
8529              If CHILD is the merge target we know that
8530              MERGE_SOURCE_PATH:MERGED_RANGE->END exists.  Further, if there
8531              were no copies in MERGE_SOURCE_PATH's history going back to
8532              RANGE->START then we know that
8533              MERGE_SOURCE_PATH:MERGED_RANGE->START exists too and the two
8534              describe an unbroken line of history, and thus
8535              MERGE_SOURCE_PATH:MERGED_RANGE->START:
8536              MERGE_SOURCE_PATH:MERGED_RANGE->END is a valid description of
8537              the merge -- see normalize_merge_sources() and the global comment
8538              'MERGEINFO MERGE SOURCE NORMALIZATION'.
8539
8540              However, if there *was* a copy, then
8541              MERGE_SOURCE_PATH:MERGED_RANGE->START doesn't exist or is
8542              unrelated to MERGE_SOURCE_PATH:MERGED_RANGE->END.  Also, we
8543              don't know if (MERGE_SOURCE_PATH:MERGED_RANGE->START)+1 through
8544              (MERGE_SOURCE_PATH:MERGED_RANGE->END)-1 actually exist.
8545
8546              If CHILD is a subtree of the merge target, then nothing is
8547              guaranteed beyond the fact that MERGE_SOURCE_PATH exists at
8548              MERGED_RANGE->END. */
8549           if ((!merge_b->record_only || merge_b->reintegrate_merge)
8550               && (!is_rollback))
8551             {
8552               svn_error_t *err;
8553               svn_mergeinfo_t subtree_history_as_mergeinfo;
8554               svn_rangelist_t *child_merge_src_rangelist;
8555               svn_client__pathrev_t *subtree_mergeinfo_pathrev
8556                 = svn_client__pathrev_create_with_relpath(
8557                     merge_b->target->loc.repos_root_url,
8558                     merge_b->target->loc.repos_uuid,
8559                     merged_range->end, child_merge_src_fspath + 1,
8560                     iterpool);
8561
8562               /* Confirm that the naive mergeinfo we want to set on
8563                  CHILD->ABSPATH both exists and is part of
8564                  (MERGE_SOURCE_PATH+CHILD_REPOS_PATH)@MERGED_RANGE->END's
8565                  history. */
8566               /* We know MERGED_RANGE->END is younger than MERGE_RANGE->START
8567                  because we only do this for forward merges. */
8568               err = svn_client__get_history_as_mergeinfo(
8569                 &subtree_history_as_mergeinfo, NULL,
8570                 subtree_mergeinfo_pathrev,
8571                 merged_range->end, merged_range->start,
8572                 merge_b->ra_session2, merge_b->ctx, iterpool);
8573
8574               /* If CHILD is a subtree it may have been deleted prior to
8575                  MERGED_RANGE->END so the above call to get its history
8576                  will fail. */
8577               if (err)
8578                 {
8579                   if (err->apr_err != SVN_ERR_FS_NOT_FOUND)
8580                       return svn_error_trace(err);
8581                   svn_error_clear(err);
8582                 }
8583               else
8584                 {
8585                   child_merge_src_rangelist = svn_hash_gets(
8586                                                 subtree_history_as_mergeinfo,
8587                                                 child_merge_src_fspath);
8588                   SVN_ERR(svn_rangelist_intersect(&child_merge_rangelist,
8589                                                   child_merge_rangelist,
8590                                                   child_merge_src_rangelist,
8591                                                   FALSE, iterpool));
8592                   if (child->record_noninheritable)
8593                     svn_rangelist__set_inheritance(child_merge_rangelist,
8594                                                    FALSE);
8595                 }
8596             }
8597
8598           svn_hash_sets(child_merges, child->abspath, child_merge_rangelist);
8599           SVN_ERR(update_wc_mergeinfo(result_catalog,
8600                                       child->abspath,
8601                                       child_merge_src_fspath,
8602                                       child_merges, is_rollback,
8603                                       merge_b->ctx, iterpool));
8604
8605           /* Once is enough: We don't need to record mergeinfo describing
8606              the merge a second.  If CHILD->ABSPATH is in
8607              MERGE_B->ADDED_ABSPATHS, we'll do just that, so remove the
8608              former from the latter. */
8609           svn_hash_sets(merge_b->added_abspaths, child->abspath, NULL);
8610         }
8611
8612       /* Elide explicit subtree mergeinfo whether or not we updated it. */
8613       if (i > 0)
8614         {
8615           svn_boolean_t in_switched_subtree = FALSE;
8616
8617           if (child->switched)
8618             in_switched_subtree = TRUE;
8619           else if (i > 1)
8620             {
8621               /* Check if CHILD is part of a switched subtree */
8622               svn_client__merge_path_t *parent;
8623               int j = i - 1;
8624               for (; j > 0; j--)
8625                 {
8626                   parent = APR_ARRAY_IDX(children_with_mergeinfo,
8627                                          j, svn_client__merge_path_t *);
8628                   if (parent
8629                       && parent->switched
8630                       && svn_dirent_is_ancestor(parent->abspath,
8631                                                 child->abspath))
8632                     {
8633                       in_switched_subtree = TRUE;
8634                       break;
8635                     }
8636                 }
8637             }
8638
8639           /* Allow mergeinfo on switched subtrees to elide to the
8640              repository. Otherwise limit elision to the merge target
8641              for now.  do_directory_merge() will eventually try to
8642              elide that when the merge is complete. */
8643           SVN_ERR(svn_client__elide_mergeinfo(
8644             child->abspath,
8645             in_switched_subtree ? NULL : merge_b->target->abspath,
8646             merge_b->ctx, iterpool));
8647         }
8648     } /* (i = 0; i < notify_b->children_with_mergeinfo->nelts; i++) */
8649
8650   svn_pool_destroy(iterpool);
8651   return SVN_NO_ERROR;
8652 }
8653
8654 /* Helper for do_directory_merge().
8655
8656    Record mergeinfo describing a merge of
8657    MERGED_RANGE->START:MERGED_RANGE->END from the repository relative path
8658    MERGEINFO_FSPATH to each path in ADDED_ABSPATHS which has explicit
8659    mergeinfo or is the immediate child of a parent with explicit
8660    non-inheritable mergeinfo.
8661
8662    DEPTH, MERGE_B, and SQUELCH_MERGEINFO_NOTIFICATIONS, are
8663    cascaded from do_directory_merge's arguments of the same names.
8664
8665    Note: This is intended to support forward merges only, i.e.
8666    MERGED_RANGE->START must be older than MERGED_RANGE->END.
8667 */
8668 static svn_error_t *
8669 record_mergeinfo_for_added_subtrees(
8670   svn_merge_range_t *merged_range,
8671   const char *mergeinfo_fspath,
8672   svn_depth_t depth,
8673   svn_boolean_t squelch_mergeinfo_notifications,
8674   apr_hash_t *added_abspaths,
8675   merge_cmd_baton_t *merge_b,
8676   apr_pool_t *pool)
8677 {
8678   apr_pool_t *iterpool;
8679   apr_hash_index_t *hi;
8680
8681   /* If no paths were added by the merge then we have nothing to do. */
8682   if (!added_abspaths)
8683     return SVN_NO_ERROR;
8684
8685   SVN_ERR_ASSERT(merged_range->start < merged_range->end);
8686
8687   iterpool = svn_pool_create(pool);
8688   for (hi = apr_hash_first(pool, added_abspaths); hi; hi = apr_hash_next(hi))
8689     {
8690       const char *added_abspath = svn__apr_hash_index_key(hi);
8691       const char *dir_abspath;
8692       svn_mergeinfo_t parent_mergeinfo;
8693       svn_mergeinfo_t added_path_mergeinfo;
8694
8695       svn_pool_clear(iterpool);
8696       dir_abspath = svn_dirent_dirname(added_abspath, iterpool);
8697
8698       /* Grab the added path's explicit mergeinfo. */
8699       SVN_ERR(svn_client__get_wc_mergeinfo(&added_path_mergeinfo, NULL,
8700                                            svn_mergeinfo_explicit,
8701                                            added_abspath, NULL, NULL, FALSE,
8702                                            merge_b->ctx, iterpool, iterpool));
8703
8704       /* If the added path doesn't have explicit mergeinfo, does its immediate
8705          parent have non-inheritable mergeinfo? */
8706       if (!added_path_mergeinfo)
8707         SVN_ERR(svn_client__get_wc_mergeinfo(&parent_mergeinfo, NULL,
8708                                              svn_mergeinfo_explicit,
8709                                              dir_abspath, NULL, NULL, FALSE,
8710                                              merge_b->ctx,
8711                                              iterpool, iterpool));
8712
8713       if (added_path_mergeinfo
8714           || svn_mergeinfo__is_noninheritable(parent_mergeinfo, iterpool))
8715         {
8716           svn_node_kind_t added_path_kind;
8717           svn_mergeinfo_t merge_mergeinfo;
8718           svn_mergeinfo_t adds_history_as_mergeinfo;
8719           svn_rangelist_t *rangelist;
8720           const char *rel_added_path;
8721           const char *added_path_mergeinfo_fspath;
8722           svn_client__pathrev_t *added_path_pathrev;
8723
8724           SVN_ERR(svn_wc_read_kind2(&added_path_kind, merge_b->ctx->wc_ctx,
8725                                     added_abspath, FALSE, FALSE, iterpool));
8726
8727           /* Calculate the naive mergeinfo describing the merge. */
8728           merge_mergeinfo = apr_hash_make(iterpool);
8729           rangelist = svn_rangelist__initialize(
8730                         merged_range->start, merged_range->end,
8731                         ((added_path_kind == svn_node_file)
8732                          || (!(depth == svn_depth_infinity
8733                                || depth == svn_depth_immediates))),
8734                         iterpool);
8735
8736           /* Create the new mergeinfo path for added_path's mergeinfo.
8737              (added_abspath had better be a child of MERGE_B->target->abspath
8738              or something is *really* wrong.) */
8739           rel_added_path = svn_dirent_is_child(merge_b->target->abspath,
8740                                                added_abspath, iterpool);
8741           SVN_ERR_ASSERT(rel_added_path);
8742           added_path_mergeinfo_fspath = svn_fspath__join(mergeinfo_fspath,
8743                                                          rel_added_path,
8744                                                          iterpool);
8745           svn_hash_sets(merge_mergeinfo, added_path_mergeinfo_fspath,
8746                         rangelist);
8747
8748           /* Don't add new mergeinfo to describe the merge if that mergeinfo
8749              contains non-existent merge sources.
8750
8751              We know that MERGEINFO_PATH/rel_added_path's history does not
8752              span MERGED_RANGE->START:MERGED_RANGE->END but rather that it
8753              was added at some revions greater than MERGED_RANGE->START
8754              (assuming this is a forward merge).  It may have been added,
8755              deleted, and re-added many times.  The point is that we cannot
8756              blindly apply the naive mergeinfo calculated above because it
8757              will describe non-existent merge sources. To avoid this we get
8758              take the intersection of the naive mergeinfo with
8759              MERGEINFO_PATH/rel_added_path's history. */
8760           added_path_pathrev = svn_client__pathrev_create_with_relpath(
8761                                  merge_b->target->loc.repos_root_url,
8762                                  merge_b->target->loc.repos_uuid,
8763                                  MAX(merged_range->start, merged_range->end),
8764                                  added_path_mergeinfo_fspath + 1, iterpool);
8765           SVN_ERR(svn_client__get_history_as_mergeinfo(
8766             &adds_history_as_mergeinfo, NULL,
8767             added_path_pathrev,
8768             MAX(merged_range->start, merged_range->end),
8769             MIN(merged_range->start, merged_range->end),
8770             merge_b->ra_session2, merge_b->ctx, iterpool));
8771
8772           SVN_ERR(svn_mergeinfo_intersect2(&merge_mergeinfo,
8773                                            merge_mergeinfo,
8774                                            adds_history_as_mergeinfo,
8775                                            FALSE, iterpool, iterpool));
8776
8777           /* Combine the explicit mergeinfo on the added path (if any)
8778              with the mergeinfo describing this merge. */
8779           if (added_path_mergeinfo)
8780             SVN_ERR(svn_mergeinfo_merge2(merge_mergeinfo,
8781                                          added_path_mergeinfo,
8782                                          iterpool, iterpool));
8783           SVN_ERR(svn_client__record_wc_mergeinfo(
8784             added_abspath, merge_mergeinfo,
8785             !squelch_mergeinfo_notifications, merge_b->ctx, iterpool));
8786         }
8787     }
8788   svn_pool_destroy(iterpool);
8789
8790   return SVN_NO_ERROR;
8791 }
8792 /* Baton structure for log_noop_revs. */
8793 typedef struct log_noop_baton_t
8794 {
8795   /* See the comment 'THE CHILDREN_WITH_MERGEINFO ARRAY' at the start
8796      of this file.*/
8797   apr_array_header_t *children_with_mergeinfo;
8798
8799   /* Absolute repository path of younger of the two merge sources
8800      being diffed. */
8801   const char *source_fspath;
8802
8803   /* The merge target. */
8804   const merge_target_t *target;
8805
8806   /* Initially empty rangelists allocated in POOL. The rangelists are
8807    * populated across multiple invocations of log_noop_revs(). */
8808   svn_rangelist_t *operative_ranges;
8809   svn_rangelist_t *merged_ranges;
8810
8811   /* Pool to store the rangelists. */
8812   apr_pool_t *pool;
8813 } log_noop_baton_t;
8814
8815 /* Helper for log_noop_revs: Merge a svn_merge_range_t representation of
8816    REVISION into RANGELIST. New elements added to rangelist are allocated
8817    in RESULT_POOL.
8818
8819    This is *not* a general purpose rangelist merge but a special replacement
8820    for svn_rangelist_merge when REVISION is guaranteed to be younger than any
8821    element in RANGELIST.  svn_rangelist_merge is O(n) worst-case (i.e. when
8822    all the ranges in output rangelist are older than the incoming changes).
8823    This turns the special case of a single incoming younger range into O(1).
8824    */
8825 static svn_error_t *
8826 rangelist_merge_revision(svn_rangelist_t *rangelist,
8827                          svn_revnum_t revision,
8828                          apr_pool_t *result_pool)
8829 {
8830   svn_merge_range_t *new_range;
8831   if (rangelist->nelts)
8832     {
8833       svn_merge_range_t *range = APR_ARRAY_IDX(rangelist, rangelist->nelts - 1,
8834                                                svn_merge_range_t *);
8835       if (range->end == revision - 1)
8836         {
8837           /* REVISION is adjacent to the youngest range in RANGELIST
8838              so we can simply expand that range to encompass REVISION. */
8839           range->end = revision;
8840           return SVN_NO_ERROR;
8841         }
8842     }
8843   new_range = apr_palloc(result_pool, sizeof(*new_range));
8844   new_range->start = revision - 1;
8845   new_range->end = revision;
8846   new_range->inheritable = TRUE;
8847
8848   APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = new_range;
8849
8850   return SVN_NO_ERROR;
8851 }
8852
8853 /* Implements the svn_log_entry_receiver_t interface.
8854
8855    BATON is an log_noop_baton_t *.
8856
8857    Add LOG_ENTRY->REVISION to BATON->OPERATIVE_RANGES.
8858
8859    If LOG_ENTRY->REVISION has already been fully merged to
8860    BATON->target->abspath per the mergeinfo in BATON->CHILDREN_WITH_MERGEINFO,
8861    then add LOG_ENTRY->REVISION to BATON->MERGED_RANGES.
8862
8863    Use SCRATCH_POOL for temporary allocations.  Allocate additions to
8864    BATON->MERGED_RANGES and BATON->OPERATIVE_RANGES in BATON->POOL.
8865
8866    Note: This callback must be invoked from oldest LOG_ENTRY->REVISION
8867    to youngest LOG_ENTRY->REVISION -- see rangelist_merge_revision().
8868 */
8869 static svn_error_t *
8870 log_noop_revs(void *baton,
8871               svn_log_entry_t *log_entry,
8872               apr_pool_t *scratch_pool)
8873 {
8874   log_noop_baton_t *log_gap_baton = baton;
8875   apr_hash_index_t *hi;
8876   svn_revnum_t revision;
8877   svn_boolean_t log_entry_rev_required = FALSE;
8878
8879   revision = log_entry->revision;
8880
8881   /* It's possible that authz restrictions on the merge source prevent us
8882      from knowing about any of the changes for LOG_ENTRY->REVISION. */
8883   if (!log_entry->changed_paths2)
8884     return SVN_NO_ERROR;
8885
8886   /* Unconditionally add LOG_ENTRY->REVISION to BATON->OPERATIVE_MERGES. */
8887   SVN_ERR(rangelist_merge_revision(log_gap_baton->operative_ranges,
8888                                    revision,
8889                                    log_gap_baton->pool));
8890
8891   /* Examine each path affected by LOG_ENTRY->REVISION.  If the explicit or
8892      inherited mergeinfo for *all* of the corresponding paths under
8893      BATON->target->abspath reflects that LOG_ENTRY->REVISION has been
8894      merged, then add LOG_ENTRY->REVISION to BATON->MERGED_RANGES. */
8895   for (hi = apr_hash_first(scratch_pool, log_entry->changed_paths2);
8896        hi;
8897        hi = apr_hash_next(hi))
8898     {
8899       const char *fspath = svn__apr_hash_index_key(hi);
8900       const char *rel_path;
8901       const char *cwmi_abspath;
8902       svn_rangelist_t *paths_explicit_rangelist = NULL;
8903       svn_boolean_t mergeinfo_inherited = FALSE;
8904
8905       /* Adjust REL_PATH so it is relative to the merge source then use it to
8906          calculate what path in the merge target would be affected by this
8907          revision. */
8908       rel_path = svn_fspath__skip_ancestor(log_gap_baton->source_fspath,
8909                                            fspath);
8910       /* Is PATH even within the merge target?  If it isn't we
8911          can disregard it altogether. */
8912       if (rel_path == NULL)
8913         continue;
8914       cwmi_abspath = svn_dirent_join(log_gap_baton->target->abspath,
8915                                      rel_path, scratch_pool);
8916
8917       /* Find any explicit or inherited mergeinfo for PATH. */
8918       while (!log_entry_rev_required)
8919         {
8920           svn_client__merge_path_t *child = get_child_with_mergeinfo(
8921             log_gap_baton->children_with_mergeinfo, cwmi_abspath);
8922
8923           if (child && child->pre_merge_mergeinfo)
8924             {
8925               /* Found some explicit mergeinfo, grab any ranges
8926                  for PATH. */
8927               paths_explicit_rangelist =
8928                             svn_hash_gets(child->pre_merge_mergeinfo, fspath);
8929               break;
8930             }
8931
8932           if (cwmi_abspath[0] == '\0'
8933               || svn_dirent_is_root(cwmi_abspath, strlen(cwmi_abspath))
8934               || strcmp(log_gap_baton->target->abspath, cwmi_abspath) == 0)
8935             {
8936               /* Can't crawl any higher. */
8937               break;
8938             }
8939
8940           /* Didn't find anything so crawl up to the parent. */
8941           cwmi_abspath = svn_dirent_dirname(cwmi_abspath, scratch_pool);
8942           fspath = svn_fspath__dirname(fspath, scratch_pool);
8943
8944           /* At this point *if* we find mergeinfo it will be inherited. */
8945           mergeinfo_inherited = TRUE;
8946         }
8947
8948       if (paths_explicit_rangelist)
8949         {
8950           svn_rangelist_t *intersecting_range;
8951           svn_rangelist_t *rangelist;
8952
8953           rangelist = svn_rangelist__initialize(revision - 1, revision, TRUE,
8954                                                 scratch_pool);
8955
8956           /* If PATH inherited mergeinfo we must consider inheritance in the
8957              event the inherited mergeinfo is actually non-inheritable. */
8958           SVN_ERR(svn_rangelist_intersect(&intersecting_range,
8959                                           paths_explicit_rangelist,
8960                                           rangelist,
8961                                           mergeinfo_inherited, scratch_pool));
8962
8963           if (intersecting_range->nelts == 0)
8964             log_entry_rev_required = TRUE;
8965         }
8966       else
8967         {
8968           log_entry_rev_required = TRUE;
8969         }
8970     }
8971
8972   if (!log_entry_rev_required)
8973     SVN_ERR(rangelist_merge_revision(log_gap_baton->merged_ranges,
8974                                      revision,
8975                                      log_gap_baton->pool));
8976
8977   return SVN_NO_ERROR;
8978 }
8979
8980 /* Helper for do_directory_merge().
8981
8982    SOURCE is cascaded from the argument of the same name in
8983    do_directory_merge().  TARGET is the merge target.  RA_SESSION is the
8984    session for SOURCE->loc2.
8985
8986    Find all the ranges required by subtrees in
8987    CHILDREN_WITH_MERGEINFO that are *not* required by
8988    TARGET->abspath (i.e. CHILDREN_WITH_MERGEINFO[0]).  If such
8989    ranges exist, then find any subset of ranges which, if merged, would be
8990    inoperative.  Finally, if any inoperative ranges are found then remove
8991    these ranges from all of the subtree's REMAINING_RANGES.
8992
8993    This function should only be called when honoring mergeinfo during
8994    forward merges (i.e. SOURCE->rev1 < SOURCE->rev2).
8995 */
8996 static svn_error_t *
8997 remove_noop_subtree_ranges(const merge_source_t *source,
8998                            const merge_target_t *target,
8999                            svn_ra_session_t *ra_session,
9000                            apr_array_header_t *children_with_mergeinfo,
9001                            apr_pool_t *result_pool,
9002                            apr_pool_t *scratch_pool)
9003 {
9004   /* ### Do we need to check that we are at a uniform working revision? */
9005   int i;
9006   svn_client__merge_path_t *root_child =
9007     APR_ARRAY_IDX(children_with_mergeinfo, 0, svn_client__merge_path_t *);
9008   svn_rangelist_t *requested_ranges;
9009   svn_rangelist_t *subtree_gap_ranges;
9010   svn_rangelist_t *subtree_remaining_ranges;
9011   log_noop_baton_t log_gap_baton;
9012   svn_merge_range_t *oldest_gap_rev;
9013   svn_merge_range_t *youngest_gap_rev;
9014   svn_rangelist_t *inoperative_ranges;
9015   apr_pool_t *iterpool;
9016   const char *longest_common_subtree_ancestor = NULL;
9017   svn_error_t *err;
9018
9019   assert(session_url_is(ra_session, source->loc2->url, scratch_pool));
9020
9021   /* This function is only intended to work with forward merges. */
9022   if (source->loc1->rev > source->loc2->rev)
9023     return SVN_NO_ERROR;
9024
9025   /* Another easy out: There are no subtrees. */
9026   if (children_with_mergeinfo->nelts < 2)
9027     return SVN_NO_ERROR;
9028
9029   subtree_remaining_ranges = apr_array_make(scratch_pool, 1,
9030                                             sizeof(svn_merge_range_t *));
9031
9032   /* Given the requested merge of SOURCE->rev1:rev2 might there be any
9033      part of this range required for subtrees but not for the target? */
9034   requested_ranges = svn_rangelist__initialize(MIN(source->loc1->rev,
9035                                                    source->loc2->rev),
9036                                                MAX(source->loc1->rev,
9037                                                    source->loc2->rev),
9038                                                TRUE, scratch_pool);
9039   SVN_ERR(svn_rangelist_remove(&subtree_gap_ranges,
9040                                root_child->remaining_ranges,
9041                                requested_ranges, FALSE, scratch_pool));
9042
9043   /* Early out, nothing to operate on */
9044   if (!subtree_gap_ranges->nelts)
9045     return SVN_NO_ERROR;
9046
9047   /* Create a rangelist describing every range required across all subtrees. */
9048   iterpool = svn_pool_create(scratch_pool);
9049   for (i = 1; i < children_with_mergeinfo->nelts; i++)
9050     {
9051       svn_client__merge_path_t *child =
9052         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
9053
9054       svn_pool_clear(iterpool);
9055
9056       /* Issue #4269: Keep track of the longest common ancestor of all the
9057          subtrees which require merges.  This may be a child of
9058          TARGET->ABSPATH, which will allow us to narrow the log request
9059          below. */
9060       if (child->remaining_ranges && child->remaining_ranges->nelts)
9061         {
9062           if (longest_common_subtree_ancestor)
9063             longest_common_subtree_ancestor = svn_dirent_get_longest_ancestor(
9064               longest_common_subtree_ancestor, child->abspath, scratch_pool);
9065           else
9066             longest_common_subtree_ancestor = child->abspath;
9067         }
9068
9069       /* CHILD->REMAINING_RANGES will be NULL if child is absent. */
9070       if (child->remaining_ranges && child->remaining_ranges->nelts)
9071         SVN_ERR(svn_rangelist_merge2(subtree_remaining_ranges,
9072                                      child->remaining_ranges,
9073                                      scratch_pool, iterpool));
9074     }
9075   svn_pool_destroy(iterpool);
9076
9077   /* It's possible that none of the subtrees had any remaining ranges. */
9078   if (!subtree_remaining_ranges->nelts)
9079     return SVN_NO_ERROR;
9080
9081   /* Ok, *finally* we can answer what part(s) of SOURCE->rev1:rev2 are
9082      required for the subtrees but not the target. */
9083   SVN_ERR(svn_rangelist_intersect(&subtree_gap_ranges,
9084                                   subtree_gap_ranges,
9085                                   subtree_remaining_ranges, FALSE,
9086                                   scratch_pool));
9087
9088   /* Another early out */
9089   if (!subtree_gap_ranges->nelts)
9090     return SVN_NO_ERROR;
9091
9092   /* One or more subtrees need some revisions that the target doesn't need.
9093      Use log to determine if any of these revisions are inoperative. */
9094   oldest_gap_rev = APR_ARRAY_IDX(subtree_gap_ranges, 0, svn_merge_range_t *);
9095   youngest_gap_rev = APR_ARRAY_IDX(subtree_gap_ranges,
9096                          subtree_gap_ranges->nelts - 1, svn_merge_range_t *);
9097
9098   /* Set up the log baton. */
9099   log_gap_baton.children_with_mergeinfo = children_with_mergeinfo;
9100   log_gap_baton.source_fspath
9101     = svn_client__pathrev_fspath(source->loc2, result_pool);
9102   log_gap_baton.target = target;
9103   log_gap_baton.merged_ranges = apr_array_make(scratch_pool, 0,
9104                                                sizeof(svn_revnum_t *));
9105   log_gap_baton.operative_ranges = apr_array_make(scratch_pool, 0,
9106                                                   sizeof(svn_revnum_t *));
9107   log_gap_baton.pool = svn_pool_create(scratch_pool);
9108
9109   /* Find the longest common ancestor of all subtrees relative to
9110      RA_SESSION's URL. */
9111   if (longest_common_subtree_ancestor)
9112     longest_common_subtree_ancestor =
9113       svn_dirent_skip_ancestor(target->abspath,
9114                                longest_common_subtree_ancestor);
9115   else
9116     longest_common_subtree_ancestor = "";
9117
9118   /* Invoke the svn_log_entry_receiver_t receiver log_noop_revs() from
9119      oldest to youngest.  The receiver is optimized to add ranges to
9120      log_gap_baton.merged_ranges and log_gap_baton.operative_ranges, but
9121      requires that the revs arrive oldest to youngest -- see log_noop_revs()
9122      and rangelist_merge_revision(). */
9123   err = get_log(ra_session, longest_common_subtree_ancestor,
9124                 oldest_gap_rev->start + 1, youngest_gap_rev->end, TRUE,
9125                 log_noop_revs, &log_gap_baton, scratch_pool);
9126
9127   /* It's possible that the only subtrees with mergeinfo in TARGET don't have
9128      any corresponding subtree in SOURCE between SOURCE->REV1 < SOURCE->REV2.
9129      So it's also possible that we may ask for the logs of non-existent paths.
9130      If we do, then assume that no subtree requires any ranges that are not
9131      already required by the TARGET. */
9132   if (err)
9133     {
9134       if (err->apr_err != SVN_ERR_FS_NOT_FOUND
9135           && longest_common_subtree_ancestor[0] != '\0')
9136         return svn_error_trace(err);
9137
9138       /* Asked about a non-existent subtree in SOURCE. */
9139       svn_error_clear(err);
9140       log_gap_baton.merged_ranges =
9141         svn_rangelist__initialize(oldest_gap_rev->start,
9142                                   youngest_gap_rev->end,
9143                                   TRUE, scratch_pool);
9144     }
9145   else
9146     {
9147       inoperative_ranges = svn_rangelist__initialize(oldest_gap_rev->start,
9148                                                      youngest_gap_rev->end,
9149                                                      TRUE, scratch_pool);
9150       SVN_ERR(svn_rangelist_remove(&(inoperative_ranges),
9151                                    log_gap_baton.operative_ranges,
9152                                    inoperative_ranges, FALSE, scratch_pool));
9153       SVN_ERR(svn_rangelist_merge2(log_gap_baton.merged_ranges, inoperative_ranges,
9154                                    scratch_pool, scratch_pool));
9155     }
9156
9157   for (i = 1; i < children_with_mergeinfo->nelts; i++)
9158     {
9159       svn_client__merge_path_t *child =
9160         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
9161
9162       /* CHILD->REMAINING_RANGES will be NULL if child is absent. */
9163       if (child->remaining_ranges && child->remaining_ranges->nelts)
9164         {
9165           /* Remove inoperative ranges from all children so we don't perform
9166              inoperative editor drives. */
9167           SVN_ERR(svn_rangelist_remove(&(child->remaining_ranges),
9168                                        log_gap_baton.merged_ranges,
9169                                        child->remaining_ranges,
9170                                        FALSE, result_pool));
9171         }
9172     }
9173
9174   svn_pool_destroy(log_gap_baton.pool);
9175
9176   return SVN_NO_ERROR;
9177 }
9178
9179 /* Perform a merge of changes in SOURCE to the working copy path
9180    TARGET_ABSPATH. Both URLs in SOURCE, and TARGET_ABSPATH all represent
9181    directories -- for the single file case, the caller should use
9182    do_file_merge().
9183
9184    CHILDREN_WITH_MERGEINFO and MERGE_B describe the merge being performed
9185    As this function is for a mergeinfo-aware merge, SOURCE->ancestral
9186    should be TRUE, and SOURCE->loc1 must be a historical ancestor of
9187    SOURCE->loc2, or vice-versa (see `MERGEINFO MERGE SOURCE NORMALIZATION'
9188    for more requirements around SOURCE).
9189
9190    Mergeinfo changes will be recorded unless MERGE_B->dry_run is true.
9191
9192    If mergeinfo is being recorded, SQUELCH_MERGEINFO_NOTIFICATIONS is FALSE,
9193    and MERGE_B->CTX->NOTIFY_FUNC2 is not NULL, then call
9194    MERGE_B->CTX->NOTIFY_FUNC2 with MERGE_B->CTX->NOTIFY_BATON2 and a
9195    svn_wc_notify_merge_record_info_begin notification before any mergeinfo
9196    changes are made to describe the merge performed.
9197
9198    If mergeinfo is being recorded to describe this merge, and RESULT_CATALOG
9199    is not NULL, then don't record the new mergeinfo on the WC, but instead
9200    record it in RESULT_CATALOG, where the keys are absolute working copy
9201    paths and the values are the new mergeinfos for each.  Allocate additions
9202    to RESULT_CATALOG in pool which RESULT_CATALOG was created in.
9203
9204    Handle DEPTH as documented for svn_client_merge5().
9205
9206    CONFLICT_REPORT is as documented for do_directory_merge().
9207
9208    Perform any temporary allocations in SCRATCH_POOL.
9209
9210    NOTE: This is a wrapper around drive_merge_report_editor() which
9211    handles the complexities inherent to situations where a given
9212    directory's children may have intersecting merges (because they
9213    meet one or more of the criteria described in get_mergeinfo_paths()).
9214 */
9215 static svn_error_t *
9216 do_mergeinfo_aware_dir_merge(svn_mergeinfo_catalog_t result_catalog,
9217                              single_range_conflict_report_t **conflict_report,
9218                              const merge_source_t *source,
9219                              const char *target_abspath,
9220                              apr_array_header_t *children_with_mergeinfo,
9221                              const svn_diff_tree_processor_t *processor,
9222                              svn_depth_t depth,
9223                              svn_boolean_t squelch_mergeinfo_notifications,
9224                              merge_cmd_baton_t *merge_b,
9225                              apr_pool_t *result_pool,
9226                              apr_pool_t *scratch_pool)
9227 {
9228   /* The range defining the mergeinfo we will record to describe the merge
9229      (assuming we are recording mergeinfo
9230
9231      Note: This may be a subset of SOURCE->rev1:rev2 if
9232      populate_remaining_ranges() determines that some part of
9233      SOURCE->rev1:rev2 has already been wholly merged to TARGET_ABSPATH.
9234      Also, the actual editor drive(s) may be a subset of RANGE, if
9235      remove_noop_subtree_ranges() and/or fix_deleted_subtree_ranges()
9236      further tweak things. */
9237   svn_merge_range_t range;
9238
9239   svn_ra_session_t *ra_session;
9240   svn_client__merge_path_t *target_merge_path;
9241   svn_boolean_t is_rollback = (source->loc1->rev > source->loc2->rev);
9242
9243   SVN_ERR_ASSERT(source->ancestral);
9244
9245   /*** If we get here, we're dealing with related sources from the
9246        same repository as the target -- merge tracking might be
9247        happenin'! ***/
9248
9249   *conflict_report = NULL;
9250
9251   /* Point our RA_SESSION to the URL of our youngest merge source side. */
9252   ra_session = is_rollback ? merge_b->ra_session1 : merge_b->ra_session2;
9253
9254   /* Fill NOTIFY_B->CHILDREN_WITH_MERGEINFO with child paths (const
9255      svn_client__merge_path_t *) which might have intersecting merges
9256      because they meet one or more of the criteria described in
9257      get_mergeinfo_paths(). Here the paths are arranged in a depth
9258      first order. */
9259   SVN_ERR(get_mergeinfo_paths(children_with_mergeinfo,
9260                               merge_b->target, depth,
9261                               merge_b->dry_run, merge_b->same_repos,
9262                               merge_b->ctx, scratch_pool, scratch_pool));
9263
9264   /* The first item from the NOTIFY_B->CHILDREN_WITH_MERGEINFO is always
9265      the target thanks to depth-first ordering. */
9266   target_merge_path = APR_ARRAY_IDX(children_with_mergeinfo, 0,
9267                                     svn_client__merge_path_t *);
9268
9269   /* If we are honoring mergeinfo, then for each item in
9270      NOTIFY_B->CHILDREN_WITH_MERGEINFO, we need to calculate what needs to be
9271      merged, and then merge it.  Otherwise, we just merge what we were asked
9272      to merge across the whole tree.  */
9273   SVN_ERR(populate_remaining_ranges(children_with_mergeinfo,
9274                                     source, ra_session,
9275                                     merge_b, scratch_pool, scratch_pool));
9276
9277   /* Always start with a range which describes the most inclusive merge
9278      possible, i.e. SOURCE->rev1:rev2. */
9279   range.start = source->loc1->rev;
9280   range.end = source->loc2->rev;
9281   range.inheritable = TRUE;
9282
9283   if (!merge_b->reintegrate_merge)
9284     {
9285       svn_revnum_t new_range_start, start_rev;
9286       apr_pool_t *iterpool = svn_pool_create(scratch_pool);
9287
9288       /* The merge target TARGET_ABSPATH and/or its subtrees may not need all
9289          of SOURCE->rev1:rev2 applied.  So examine
9290          NOTIFY_B->CHILDREN_WITH_MERGEINFO to find the oldest starting
9291          revision that actually needs to be merged (for reverse merges this is
9292          the youngest starting revision).
9293
9294          We'll do this twice, right now for the start of the mergeinfo we will
9295          ultimately record to describe this merge and then later for the
9296          start of the actual editor drive. */
9297       new_range_start = get_most_inclusive_rev(
9298         children_with_mergeinfo, is_rollback, TRUE);
9299       if (SVN_IS_VALID_REVNUM(new_range_start))
9300         range.start = new_range_start;
9301
9302       /* Remove inoperative ranges from any subtrees' remaining_ranges
9303          to spare the expense of noop editor drives. */
9304       if (!is_rollback)
9305         SVN_ERR(remove_noop_subtree_ranges(source, merge_b->target,
9306                                            ra_session,
9307                                            children_with_mergeinfo,
9308                                            scratch_pool, iterpool));
9309
9310       /* Adjust subtrees' remaining_ranges to deal with issue #3067:
9311        * "subtrees that don't exist at the start or end of a merge range
9312        * shouldn't break the merge". */
9313       SVN_ERR(fix_deleted_subtree_ranges(source, merge_b->target,
9314                                          ra_session,
9315                                          children_with_mergeinfo,
9316                                          merge_b->ctx, scratch_pool, iterpool));
9317
9318       /* remove_noop_subtree_ranges() and/or fix_deleted_subtree_range()
9319          may have further refined the starting revision for our editor
9320          drive. */
9321       start_rev =
9322         get_most_inclusive_rev(children_with_mergeinfo,
9323                                is_rollback, TRUE);
9324
9325       /* Is there anything to merge? */
9326       if (SVN_IS_VALID_REVNUM(start_rev))
9327         {
9328           /* Now examine NOTIFY_B->CHILDREN_WITH_MERGEINFO to find the oldest
9329              ending revision that actually needs to be merged (for reverse
9330              merges this is the youngest ending revision). */
9331            svn_revnum_t end_rev =
9332              get_most_inclusive_rev(children_with_mergeinfo,
9333                                     is_rollback, FALSE);
9334
9335           /* While END_REV is valid, do the following:
9336
9337              1. Tweak each NOTIFY_B->CHILDREN_WITH_MERGEINFO element so that
9338                 the element's remaining_ranges member has as its first element
9339                 a range that ends with end_rev.
9340
9341              2. Starting with start_rev, call drive_merge_report_editor()
9342                 on MERGE_B->target->abspath for start_rev:end_rev.
9343
9344              3. Remove the first element from each
9345                 NOTIFY_B->CHILDREN_WITH_MERGEINFO element's remaining_ranges
9346                 member.
9347
9348              4. Again examine NOTIFY_B->CHILDREN_WITH_MERGEINFO to find the most
9349                 inclusive starting revision that actually needs to be merged and
9350                 update start_rev.  This prevents us from needlessly contacting the
9351                 repository and doing a diff where we describe the entire target
9352                 tree as *not* needing any of the requested range.  This can happen
9353                 whenever we have mergeinfo with gaps in it for the merge source.
9354
9355              5. Again examine NOTIFY_B->CHILDREN_WITH_MERGEINFO to find the most
9356                 inclusive ending revision that actually needs to be merged and
9357                 update end_rev.
9358
9359              6. Lather, rinse, repeat.
9360           */
9361
9362           while (end_rev != SVN_INVALID_REVNUM)
9363             {
9364               merge_source_t *real_source;
9365               svn_merge_range_t *first_target_range
9366                 = (target_merge_path->remaining_ranges->nelts == 0 ? NULL
9367                    : APR_ARRAY_IDX(target_merge_path->remaining_ranges, 0,
9368                                    svn_merge_range_t *));
9369
9370               /* Issue #3324: Stop editor abuse!  Don't call
9371                  drive_merge_report_editor() in such a way that we request an
9372                  editor with svn_client__get_diff_editor() for some rev X,
9373                  then call svn_ra_do_diff3() for some revision Y, and then
9374                  call reporter->set_path(PATH=="") to set the root revision
9375                  for the editor drive to revision Z where
9376                  (X != Z && X < Z < Y).  This is bogus because the server will
9377                  send us the diff between X:Y but the client is expecting the
9378                  diff between Y:Z.  See issue #3324 for full details on the
9379                  problems this can cause. */
9380               if (first_target_range
9381                   && start_rev != first_target_range->start)
9382                 {
9383                   if (is_rollback)
9384                     {
9385                       if (end_rev < first_target_range->start)
9386                         end_rev = first_target_range->start;
9387                     }
9388                   else
9389                     {
9390                       if (end_rev > first_target_range->start)
9391                         end_rev = first_target_range->start;
9392                     }
9393                 }
9394
9395               svn_pool_clear(iterpool);
9396
9397               slice_remaining_ranges(children_with_mergeinfo,
9398                                      is_rollback, end_rev, scratch_pool);
9399
9400               /* Reset variables that must be reset for every drive */
9401               merge_b->notify_begin.last_abspath = NULL;
9402
9403               real_source = subrange_source(source, start_rev, end_rev, iterpool);
9404               SVN_ERR(drive_merge_report_editor(
9405                 merge_b->target->abspath,
9406                 real_source,
9407                 children_with_mergeinfo,
9408                 processor,
9409                 depth,
9410                 merge_b,
9411                 iterpool));
9412
9413               /* If any paths picked up explicit mergeinfo as a result of
9414                  the merge we need to make sure any mergeinfo those paths
9415                  inherited is recorded and then add these paths to
9416                  NOTIFY_B->CHILDREN_WITH_MERGEINFO.*/
9417               SVN_ERR(process_children_with_new_mergeinfo(
9418                         merge_b, children_with_mergeinfo,
9419                         scratch_pool));
9420
9421               /* If any subtrees had their explicit mergeinfo deleted as a
9422                  result of the merge then remove these paths from
9423                  NOTIFY_B->CHILDREN_WITH_MERGEINFO since there is no need
9424                  to consider these subtrees for subsequent editor drives
9425                  nor do we want to record mergeinfo on them describing
9426                  the merge itself. */
9427               remove_children_with_deleted_mergeinfo(
9428                 merge_b, children_with_mergeinfo);
9429
9430               /* Prepare for the next iteration (if any). */
9431               remove_first_range_from_remaining_ranges(
9432                 end_rev, children_with_mergeinfo, scratch_pool);
9433
9434               /* If we raised any conflicts, break out and report how much
9435                  we have merged. */
9436               if (is_path_conflicted_by_merge(merge_b))
9437                 {
9438                   merge_source_t *remaining_range = NULL;
9439
9440                   if (real_source->loc2->rev != source->loc2->rev)
9441                     remaining_range = subrange_source(source,
9442                                                       real_source->loc2->rev,
9443                                                       source->loc2->rev,
9444                                                       scratch_pool);
9445                   *conflict_report = single_range_conflict_report_create(
9446                                        real_source, remaining_range,
9447                                        result_pool);
9448
9449                   range.end = end_rev;
9450                   break;
9451                 }
9452
9453               start_rev =
9454                 get_most_inclusive_rev(children_with_mergeinfo,
9455                                        is_rollback, TRUE);
9456               end_rev =
9457                 get_most_inclusive_rev(children_with_mergeinfo,
9458                                        is_rollback, FALSE);
9459             }
9460         }
9461       svn_pool_destroy(iterpool);
9462     }
9463   else
9464     {
9465       if (!merge_b->record_only)
9466         {
9467           /* Reset cur_ancestor_abspath to null so that subsequent cherry
9468              picked revision ranges will be notified upon subsequent
9469              operative merge. */
9470           merge_b->notify_begin.last_abspath = NULL;
9471
9472           SVN_ERR(drive_merge_report_editor(merge_b->target->abspath,
9473                                             source,
9474                                             NULL,
9475                                             processor,
9476                                             depth,
9477                                             merge_b,
9478                                             scratch_pool));
9479         }
9480     }
9481
9482   /* Record mergeinfo where appropriate.*/
9483   if (RECORD_MERGEINFO(merge_b))
9484     {
9485       const svn_client__pathrev_t *primary_src
9486         = is_rollback ? source->loc1 : source->loc2;
9487       const char *mergeinfo_path
9488         = svn_client__pathrev_fspath(primary_src, scratch_pool);
9489
9490       SVN_ERR(record_mergeinfo_for_dir_merge(result_catalog,
9491                                              &range,
9492                                              mergeinfo_path,
9493                                              children_with_mergeinfo,
9494                                              depth,
9495                                              squelch_mergeinfo_notifications,
9496                                              merge_b,
9497                                              scratch_pool));
9498
9499       /* If a path has an immediate parent with non-inheritable mergeinfo at
9500          this point, then it meets criteria 3 or 5 described in
9501          get_mergeinfo_paths' doc string.  For paths which exist prior to a
9502          merge explicit mergeinfo has already been set.  But for paths added
9503          during the merge this is not the case.  The path might have explicit
9504          mergeinfo from the merge source, but no mergeinfo yet exists
9505          describing *this* merge.  So the added path has either incomplete
9506          explicit mergeinfo or inherits incomplete mergeinfo from its
9507          immediate parent (if any, the parent might have only non-inheritable
9508          ranges in which case the path simply inherits empty mergeinfo).
9509
9510          So here we look at the root path of each subtree added during the
9511          merge and set explicit mergeinfo on it if it meets the aforementioned
9512          conditions. */
9513       if (range.start < range.end) /* Nothing to record on added subtrees
9514                                       resulting from reverse merges. */
9515         {
9516           SVN_ERR(record_mergeinfo_for_added_subtrees(
9517                     &range, mergeinfo_path, depth,
9518                     squelch_mergeinfo_notifications,
9519                     merge_b->added_abspaths, merge_b, scratch_pool));
9520         }
9521     }
9522
9523   return SVN_NO_ERROR;
9524 }
9525
9526 /* Helper for do_merge() when the merge target is a directory.
9527  *
9528  * If any conflict is raised during the merge, set *CONFLICTED_RANGE to
9529  * the revision sub-range that raised the conflict.  In this case, the
9530  * merge will have ended at revision CONFLICTED_RANGE and mergeinfo will
9531  * have been recorded for all revision sub-ranges up to and including
9532  * CONFLICTED_RANGE.  Otherwise, set *CONFLICTED_RANGE to NULL.
9533  */
9534 static svn_error_t *
9535 do_directory_merge(svn_mergeinfo_catalog_t result_catalog,
9536                    single_range_conflict_report_t **conflict_report,
9537                    const merge_source_t *source,
9538                    const char *target_abspath,
9539                    const svn_diff_tree_processor_t *processor,
9540                    svn_depth_t depth,
9541                    svn_boolean_t squelch_mergeinfo_notifications,
9542                    merge_cmd_baton_t *merge_b,
9543                    apr_pool_t *result_pool,
9544                    apr_pool_t *scratch_pool)
9545 {
9546   apr_array_header_t *children_with_mergeinfo;
9547
9548   /* Initialize CHILDREN_WITH_MERGEINFO. See the comment
9549      'THE CHILDREN_WITH_MERGEINFO ARRAY' at the start of this file. */
9550   children_with_mergeinfo =
9551     apr_array_make(scratch_pool, 16, sizeof(svn_client__merge_path_t *));
9552
9553   /* And make it read-only accessible from the baton */
9554   merge_b->notify_begin.nodes_with_mergeinfo = children_with_mergeinfo;
9555
9556   /* If we are not honoring mergeinfo we can skip right to the
9557      business of merging changes! */
9558   if (HONOR_MERGEINFO(merge_b))
9559     SVN_ERR(do_mergeinfo_aware_dir_merge(result_catalog, conflict_report,
9560                                          source, target_abspath,
9561                                          children_with_mergeinfo,
9562                                          processor, depth,
9563                                          squelch_mergeinfo_notifications,
9564                                          merge_b, result_pool, scratch_pool));
9565   else
9566     SVN_ERR(do_mergeinfo_unaware_dir_merge(conflict_report,
9567                                            source, target_abspath,
9568                                            children_with_mergeinfo,
9569                                            processor, depth,
9570                                            merge_b, result_pool, scratch_pool));
9571
9572   merge_b->notify_begin.nodes_with_mergeinfo = NULL;
9573
9574   return SVN_NO_ERROR;
9575 }
9576
9577 /** Ensure that *RA_SESSION is opened to URL, either by reusing
9578  * *RA_SESSION if it is non-null and already opened to URL's
9579  * repository, or by allocating a new *RA_SESSION in POOL.
9580  * (RA_SESSION itself cannot be null, of course.)
9581  *
9582  * CTX is used as for svn_client_open_ra_session().
9583  */
9584 static svn_error_t *
9585 ensure_ra_session_url(svn_ra_session_t **ra_session,
9586                       const char *url,
9587                       const char *wri_abspath,
9588                       svn_client_ctx_t *ctx,
9589                       apr_pool_t *pool)
9590 {
9591   svn_error_t *err = SVN_NO_ERROR;
9592
9593   if (*ra_session)
9594     {
9595       err = svn_ra_reparent(*ra_session, url, pool);
9596     }
9597
9598   /* SVN_ERR_RA_ILLEGAL_URL is raised when url doesn't point to the same
9599      repository as ra_session. */
9600   if (! *ra_session || (err && err->apr_err == SVN_ERR_RA_ILLEGAL_URL))
9601     {
9602       svn_error_clear(err);
9603       err = svn_client_open_ra_session2(ra_session, url, wri_abspath,
9604                                         ctx, pool, pool);
9605     }
9606   SVN_ERR(err);
9607
9608   return SVN_NO_ERROR;
9609 }
9610
9611 /* Drive a merge of MERGE_SOURCES into working copy node TARGET
9612    and possibly record mergeinfo describing the merge -- see
9613    RECORD_MERGEINFO().
9614
9615    If MODIFIED_SUBTREES is not NULL and all the MERGE_SOURCES are 'ancestral'
9616    or REINTEGRATE_MERGE is true, then replace *MODIFIED_SUBTREES with a new
9617    hash containing all the paths that *MODIFIED_SUBTREES contained before,
9618    and also every path modified, skipped, added, or tree-conflicted
9619    by the merge.  Keys and values of the hash are both (const char *)
9620    absolute paths.  The contents of the hash are allocated in RESULT_POOL.
9621
9622    If the merge raises any conflicts while merging a revision range, return
9623    early and set *CONFLICT_REPORT to describe the details.  (In this case,
9624    notify that the merge is complete if and only if this was the last
9625    revision range of the merge.)  If there are no conflicts, set
9626    *CONFLICT_REPORT to NULL.  A revision range here can be one specified
9627    in MERGE_SOURCES or an internally generated sub-range of one of those
9628    when merge tracking is in use.
9629
9630    For every (const merge_source_t *) merge source in MERGE_SOURCES, if
9631    SOURCE->ANCESTRAL is set, then the "left" and "right" side are
9632    ancestrally related.  (See 'MERGEINFO MERGE SOURCE NORMALIZATION'
9633    for more on what that means and how it matters.)
9634
9635    If SOURCES_RELATED is set, the "left" and "right" sides of the
9636    merge source are historically related (ancestors, uncles, second
9637    cousins thrice removed, etc...).  (This is passed through to
9638    do_file_merge() to simulate the history checks that the repository
9639    logic does in the directory case.)
9640
9641    SAME_REPOS is TRUE iff the merge sources live in the same
9642    repository as the one from which the target working copy has been
9643    checked out.
9644
9645    If mergeinfo is being recorded, SQUELCH_MERGEINFO_NOTIFICATIONS is FALSE,
9646    and CTX->NOTIFY_FUNC2 is not NULL, then call CTX->NOTIFY_FUNC2 with
9647    CTX->NOTIFY_BATON2 and a svn_wc_notify_merge_record_info_begin
9648    notification before any mergeinfo changes are made to describe the merge
9649    performed.
9650
9651    If mergeinfo is being recorded to describe this merge, and RESULT_CATALOG
9652    is not NULL, then don't record the new mergeinfo on the WC, but instead
9653    record it in RESULT_CATALOG, where the keys are absolute working copy
9654    paths and the values are the new mergeinfos for each.  Allocate additions
9655    to RESULT_CATALOG in pool which RESULT_CATALOG was created in.
9656
9657    FORCE_DELETE, DRY_RUN, RECORD_ONLY, DEPTH, MERGE_OPTIONS,
9658    and CTX are as described in the docstring for svn_client_merge_peg3().
9659
9660    If IGNORE_MERGEINFO is true, disable merge tracking, by treating the two
9661    sources as unrelated even if they actually have a common ancestor.  See
9662    the macro HONOR_MERGEINFO().
9663
9664    If DIFF_IGNORE_ANCESTRY is true, diff the 'left' and 'right' versions
9665    of a node (if they are the same kind) as if they were related, even if
9666    they are not related.  Otherwise, diff unrelated items as a deletion
9667    of one thing and the addition of another.
9668
9669    If not NULL, RECORD_ONLY_PATHS is a hash of (const char *) paths mapped
9670    to the same.  If RECORD_ONLY is true and RECORD_ONLY_PATHS is not NULL,
9671    then record mergeinfo describing the merge only on subtrees which contain
9672    items from RECORD_ONLY_PATHS.  If RECORD_ONLY is true and RECORD_ONLY_PATHS
9673    is NULL, then record mergeinfo on every subtree with mergeinfo in
9674    TARGET.
9675
9676    REINTEGRATE_MERGE is TRUE if this is a reintegrate merge.
9677
9678    *USE_SLEEP will be set TRUE if a sleep is required to ensure timestamp
9679    integrity, *USE_SLEEP will be unchanged if no sleep is required.
9680
9681    SCRATCH_POOL is used for all temporary allocations.
9682 */
9683 static svn_error_t *
9684 do_merge(apr_hash_t **modified_subtrees,
9685          svn_mergeinfo_catalog_t result_catalog,
9686          conflict_report_t **conflict_report,
9687          svn_boolean_t *use_sleep,
9688          const apr_array_header_t *merge_sources,
9689          const merge_target_t *target,
9690          svn_ra_session_t *src_session,
9691          svn_boolean_t sources_related,
9692          svn_boolean_t same_repos,
9693          svn_boolean_t ignore_mergeinfo,
9694          svn_boolean_t diff_ignore_ancestry,
9695          svn_boolean_t force_delete,
9696          svn_boolean_t dry_run,
9697          svn_boolean_t record_only,
9698          apr_hash_t *record_only_paths,
9699          svn_boolean_t reintegrate_merge,
9700          svn_boolean_t squelch_mergeinfo_notifications,
9701          svn_depth_t depth,
9702          const apr_array_header_t *merge_options,
9703          svn_client_ctx_t *ctx,
9704          apr_pool_t *result_pool,
9705          apr_pool_t *scratch_pool)
9706 {
9707   merge_cmd_baton_t merge_cmd_baton = { 0 };
9708   svn_config_t *cfg;
9709   const char *diff3_cmd;
9710   const char *preserved_exts_str;
9711   int i;
9712   svn_boolean_t checked_mergeinfo_capability = FALSE;
9713   svn_ra_session_t *ra_session1 = NULL, *ra_session2 = NULL;
9714   const char *old_src_session_url = NULL;
9715   apr_pool_t *iterpool;
9716   const svn_diff_tree_processor_t *processor;
9717
9718   SVN_ERR_ASSERT(svn_dirent_is_absolute(target->abspath));
9719
9720   *conflict_report = NULL;
9721
9722   /* Check from some special conditions when in record-only mode
9723      (which is a merge-tracking thing). */
9724   if (record_only)
9725     {
9726       svn_boolean_t sources_ancestral = TRUE;
9727       int j;
9728
9729       /* Find out whether all of the sources are 'ancestral'. */
9730       for (j = 0; j < merge_sources->nelts; j++)
9731         if (! APR_ARRAY_IDX(merge_sources, j, merge_source_t *)->ancestral)
9732           {
9733             sources_ancestral = FALSE;
9734             break;
9735           }
9736
9737       /* We can't do a record-only merge if the sources aren't related. */
9738       if (! sources_ancestral)
9739         return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
9740                                 _("Use of two URLs is not compatible with "
9741                                   "mergeinfo modification"));
9742
9743       /* We can't do a record-only merge if the sources aren't from
9744          the same repository as the target. */
9745       if (! same_repos)
9746         return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
9747                                 _("Merge from foreign repository is not "
9748                                   "compatible with mergeinfo modification"));
9749
9750       /* If this is a dry-run record-only merge, there's nothing to do. */
9751       if (dry_run)
9752         return SVN_NO_ERROR;
9753     }
9754
9755   iterpool = svn_pool_create(scratch_pool);
9756
9757   /* Ensure a known depth. */
9758   if (depth == svn_depth_unknown)
9759     depth = svn_depth_infinity;
9760
9761   /* Set up the diff3 command, so various callers don't have to. */
9762   cfg = ctx->config
9763         ? svn_hash_gets(ctx->config, SVN_CONFIG_CATEGORY_CONFIG)
9764         : NULL;
9765   svn_config_get(cfg, &diff3_cmd, SVN_CONFIG_SECTION_HELPERS,
9766                  SVN_CONFIG_OPTION_DIFF3_CMD, NULL);
9767
9768   if (diff3_cmd != NULL)
9769     SVN_ERR(svn_path_cstring_to_utf8(&diff3_cmd, diff3_cmd, scratch_pool));
9770
9771     /* See which files the user wants to preserve the extension of when
9772      conflict files are made. */
9773   svn_config_get(cfg, &preserved_exts_str, SVN_CONFIG_SECTION_MISCELLANY,
9774                  SVN_CONFIG_OPTION_PRESERVED_CF_EXTS, "");
9775
9776   /* Build the merge context baton (or at least the parts of it that
9777      don't need to be reset for each merge source).  */
9778   merge_cmd_baton.force_delete = force_delete;
9779   merge_cmd_baton.dry_run = dry_run;
9780   merge_cmd_baton.record_only = record_only;
9781   merge_cmd_baton.ignore_mergeinfo = ignore_mergeinfo;
9782   merge_cmd_baton.diff_ignore_ancestry = diff_ignore_ancestry;
9783   merge_cmd_baton.same_repos = same_repos;
9784   merge_cmd_baton.mergeinfo_capable = FALSE;
9785   merge_cmd_baton.ctx = ctx;
9786   merge_cmd_baton.reintegrate_merge = reintegrate_merge;
9787   merge_cmd_baton.target = target;
9788   merge_cmd_baton.pool = iterpool;
9789   merge_cmd_baton.merge_options = merge_options;
9790   merge_cmd_baton.diff3_cmd = diff3_cmd;
9791   merge_cmd_baton.ext_patterns = *preserved_exts_str
9792                           ? svn_cstring_split(preserved_exts_str, "\n\r\t\v ",
9793                                               FALSE, scratch_pool)
9794                           : NULL;
9795
9796   merge_cmd_baton.use_sleep = use_sleep;
9797
9798   /* Do we already know the specific subtrees with mergeinfo we want
9799      to record-only mergeinfo on? */
9800   if (record_only && record_only_paths)
9801     merge_cmd_baton.merged_abspaths = record_only_paths;
9802   else
9803     merge_cmd_baton.merged_abspaths = apr_hash_make(result_pool);
9804
9805   merge_cmd_baton.skipped_abspaths = apr_hash_make(result_pool);
9806   merge_cmd_baton.added_abspaths = apr_hash_make(result_pool);
9807   merge_cmd_baton.tree_conflicted_abspaths = apr_hash_make(result_pool);
9808
9809   {
9810     svn_diff_tree_processor_t *merge_processor;
9811
9812     merge_processor = svn_diff__tree_processor_create(&merge_cmd_baton,
9813                                                       scratch_pool);
9814
9815     merge_processor->dir_opened   = merge_dir_opened;
9816     merge_processor->dir_changed  = merge_dir_changed;
9817     merge_processor->dir_added    = merge_dir_added;
9818     merge_processor->dir_deleted  = merge_dir_deleted;
9819     merge_processor->dir_closed   = merge_dir_closed;
9820
9821     merge_processor->file_opened  = merge_file_opened;
9822     merge_processor->file_changed = merge_file_changed;
9823     merge_processor->file_added   = merge_file_added;
9824     merge_processor->file_deleted = merge_file_deleted;
9825     /* Not interested in file_closed() */
9826
9827     merge_processor->node_absent = merge_node_absent;
9828
9829     processor = merge_processor;
9830   }
9831
9832   if (src_session)
9833     {
9834       SVN_ERR(svn_ra_get_session_url(src_session, &old_src_session_url,
9835                                      scratch_pool));
9836       ra_session1 = src_session;
9837     }
9838
9839   for (i = 0; i < merge_sources->nelts; i++)
9840     {
9841       svn_node_kind_t src1_kind;
9842       merge_source_t *source =
9843         APR_ARRAY_IDX(merge_sources, i, merge_source_t *);
9844       single_range_conflict_report_t *conflicted_range_report;
9845
9846       svn_pool_clear(iterpool);
9847
9848       /* Sanity check:  if our left- and right-side merge sources are
9849          the same, there's nothing to here. */
9850       if ((strcmp(source->loc1->url, source->loc2->url) == 0)
9851           && (source->loc1->rev == source->loc2->rev))
9852         continue;
9853
9854       /* Establish RA sessions to our URLs, reuse where possible. */
9855       SVN_ERR(ensure_ra_session_url(&ra_session1, source->loc1->url,
9856                                     target->abspath, ctx, scratch_pool));
9857       SVN_ERR(ensure_ra_session_url(&ra_session2, source->loc2->url,
9858                                     target->abspath, ctx, scratch_pool));
9859
9860       /* Populate the portions of the merge context baton that need to
9861          be reset for each merge source iteration. */
9862       merge_cmd_baton.merge_source = *source;
9863       merge_cmd_baton.implicit_src_gap = NULL;
9864       merge_cmd_baton.conflicted_paths = NULL;
9865       merge_cmd_baton.paths_with_new_mergeinfo = NULL;
9866       merge_cmd_baton.paths_with_deleted_mergeinfo = NULL;
9867       merge_cmd_baton.ra_session1 = ra_session1;
9868       merge_cmd_baton.ra_session2 = ra_session2;
9869
9870       merge_cmd_baton.notify_begin.last_abspath = NULL;
9871
9872       /* Populate the portions of the merge context baton that require
9873          an RA session to set, but shouldn't be reset for each iteration. */
9874       if (! checked_mergeinfo_capability)
9875         {
9876           SVN_ERR(svn_ra_has_capability(ra_session1,
9877                                         &merge_cmd_baton.mergeinfo_capable,
9878                                         SVN_RA_CAPABILITY_MERGEINFO,
9879                                         iterpool));
9880           checked_mergeinfo_capability = TRUE;
9881         }
9882
9883       SVN_ERR(svn_ra_check_path(ra_session1, "", source->loc1->rev,
9884                                 &src1_kind, iterpool));
9885
9886       /* Run the merge; if there are conflicts, allow the callback to
9887        * resolve them, and if it resolves all of them, then run the
9888        * merge again with the remaining revision range, until it is all
9889        * done. */
9890       do
9891         {
9892           /* Merge as far as possible without resolving any conflicts */
9893           if (src1_kind != svn_node_dir)
9894             {
9895               SVN_ERR(do_file_merge(result_catalog, &conflicted_range_report,
9896                                     source, target->abspath,
9897                                     processor,
9898                                     sources_related,
9899                                     squelch_mergeinfo_notifications,
9900                                     &merge_cmd_baton, iterpool, iterpool));
9901             }
9902           else /* Directory */
9903             {
9904               SVN_ERR(do_directory_merge(result_catalog, &conflicted_range_report,
9905                                          source, target->abspath,
9906                                          processor,
9907                                          depth, squelch_mergeinfo_notifications,
9908                                          &merge_cmd_baton, iterpool, iterpool));
9909             }
9910
9911           /* Give the conflict resolver callback the opportunity to
9912            * resolve any conflicts that were raised.  If it resolves all
9913            * of them, go around again to merge the next sub-range (if any). */
9914           if (conflicted_range_report && ctx->conflict_func2 && ! dry_run)
9915             {
9916               svn_boolean_t conflicts_remain;
9917
9918               SVN_ERR(svn_client__resolve_conflicts(
9919                         &conflicts_remain, merge_cmd_baton.conflicted_paths,
9920                         ctx, iterpool));
9921               if (conflicts_remain)
9922                 break;
9923
9924               merge_cmd_baton.conflicted_paths = NULL;
9925               /* Caution: this source is in iterpool */
9926               source = conflicted_range_report->remaining_source;
9927               conflicted_range_report = NULL;
9928             }
9929           else
9930             break;
9931         }
9932       while (source);
9933
9934       /* The final mergeinfo on TARGET_WCPATH may itself elide. */
9935       if (! dry_run)
9936         SVN_ERR(svn_client__elide_mergeinfo(target->abspath, NULL,
9937                                             ctx, iterpool));
9938
9939       /* If conflicts occurred while merging any but the very last
9940        * range of a multi-pass merge, we raise an error that aborts
9941        * the merge. The user will be asked to resolve conflicts
9942        * before merging subsequent revision ranges. */
9943       if (conflicted_range_report)
9944         {
9945           *conflict_report = conflict_report_create(
9946                                target->abspath, conflicted_range_report->conflicted_range,
9947                                (i == merge_sources->nelts - 1
9948                                 && ! conflicted_range_report->remaining_source),
9949                                result_pool);
9950           break;
9951         }
9952     }
9953
9954   if (! *conflict_report || (*conflict_report)->was_last_range)
9955     {
9956       /* Let everyone know we're finished here. */
9957       notify_merge_completed(target->abspath, ctx, iterpool);
9958     }
9959
9960   /* Does the caller want to know what the merge has done? */
9961   if (modified_subtrees)
9962     {
9963       *modified_subtrees =
9964           apr_hash_overlay(result_pool, *modified_subtrees,
9965                            merge_cmd_baton.merged_abspaths);
9966       *modified_subtrees =
9967           apr_hash_overlay(result_pool, *modified_subtrees,
9968                            merge_cmd_baton.added_abspaths);
9969       *modified_subtrees =
9970           apr_hash_overlay(result_pool, *modified_subtrees,
9971                            merge_cmd_baton.skipped_abspaths);
9972       *modified_subtrees =
9973           apr_hash_overlay(result_pool, *modified_subtrees,
9974                            merge_cmd_baton.tree_conflicted_abspaths);
9975     }
9976
9977   if (src_session)
9978     SVN_ERR(svn_ra_reparent(src_session, old_src_session_url, iterpool));
9979
9980   svn_pool_destroy(iterpool);
9981   return SVN_NO_ERROR;
9982 }
9983
9984 /* Perform a two-URL merge between URLs which are related, but neither
9985    is a direct ancestor of the other.  This first does a real two-URL
9986    merge (unless this is record-only), followed by record-only merges
9987    to represent the changed mergeinfo.
9988
9989    Set *CONFLICT_REPORT to indicate if there were any conflicts, as in
9990    do_merge().
9991
9992    The diff to be merged is between SOURCE->loc1 (in URL1_RA_SESSION1)
9993    and SOURCE->loc2 (in URL2_RA_SESSION2); YCA is their youngest
9994    common ancestor.
9995
9996    SAME_REPOS must be true if and only if the source URLs are in the same
9997    repository as the target working copy.
9998
9999    DIFF_IGNORE_ANCESTRY is as in do_merge().
10000
10001    Other arguments are as in all of the public merge APIs.
10002
10003    *USE_SLEEP will be set TRUE if a sleep is required to ensure timestamp
10004    integrity, *USE_SLEEP will be unchanged if no sleep is required.
10005
10006    SCRATCH_POOL is used for all temporary allocations.
10007  */
10008 static svn_error_t *
10009 merge_cousins_and_supplement_mergeinfo(conflict_report_t **conflict_report,
10010                                        svn_boolean_t *use_sleep,
10011                                        const merge_target_t *target,
10012                                        svn_ra_session_t *URL1_ra_session,
10013                                        svn_ra_session_t *URL2_ra_session,
10014                                        const merge_source_t *source,
10015                                        const svn_client__pathrev_t *yca,
10016                                        svn_boolean_t same_repos,
10017                                        svn_depth_t depth,
10018                                        svn_boolean_t diff_ignore_ancestry,
10019                                        svn_boolean_t force_delete,
10020                                        svn_boolean_t record_only,
10021                                        svn_boolean_t dry_run,
10022                                        const apr_array_header_t *merge_options,
10023                                        svn_client_ctx_t *ctx,
10024                                        apr_pool_t *result_pool,
10025                                        apr_pool_t *scratch_pool)
10026 {
10027   apr_array_header_t *remove_sources, *add_sources;
10028   apr_hash_t *modified_subtrees = NULL;
10029
10030   /* Sure we could use SCRATCH_POOL throughout this function, but since this
10031      is a wrapper around three separate merges we'll create a subpool we can
10032      clear between each of the three.  If the merge target has a lot of
10033      subtree mergeinfo, then this will help keep memory use in check. */
10034   apr_pool_t *subpool = svn_pool_create(scratch_pool);
10035
10036   assert(session_url_is(URL1_ra_session, source->loc1->url, scratch_pool));
10037   assert(session_url_is(URL2_ra_session, source->loc2->url, scratch_pool));
10038
10039   SVN_ERR_ASSERT(svn_dirent_is_absolute(target->abspath));
10040   SVN_ERR_ASSERT(! source->ancestral);
10041
10042   SVN_ERR(normalize_merge_sources_internal(
10043             &remove_sources, source->loc1,
10044             svn_rangelist__initialize(source->loc1->rev, yca->rev, TRUE,
10045                                       scratch_pool),
10046             URL1_ra_session, ctx, scratch_pool, subpool));
10047
10048   SVN_ERR(normalize_merge_sources_internal(
10049             &add_sources, source->loc2,
10050             svn_rangelist__initialize(yca->rev, source->loc2->rev, TRUE,
10051                                       scratch_pool),
10052             URL2_ra_session, ctx, scratch_pool, subpool));
10053
10054   *conflict_report = NULL;
10055
10056   /* If this isn't a record-only merge, we'll first do a stupid
10057      point-to-point merge... */
10058   if (! record_only)
10059     {
10060       apr_array_header_t *faux_sources =
10061         apr_array_make(scratch_pool, 1, sizeof(merge_source_t *));
10062
10063       modified_subtrees = apr_hash_make(scratch_pool);
10064       APR_ARRAY_PUSH(faux_sources, const merge_source_t *) = source;
10065       SVN_ERR(do_merge(&modified_subtrees, NULL, conflict_report, use_sleep,
10066                        faux_sources, target,
10067                        URL1_ra_session, TRUE, same_repos,
10068                        FALSE /*ignore_mergeinfo*/, diff_ignore_ancestry,
10069                        force_delete, dry_run, FALSE, NULL, TRUE,
10070                        FALSE, depth, merge_options, ctx,
10071                        scratch_pool, subpool));
10072       if (*conflict_report)
10073         {
10074           *conflict_report = conflict_report_dup(*conflict_report, result_pool);
10075           if (! (*conflict_report)->was_last_range)
10076             return SVN_NO_ERROR;
10077         }
10078     }
10079   else if (! same_repos)
10080     {
10081       return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
10082                               _("Merge from foreign repository is not "
10083                                 "compatible with mergeinfo modification"));
10084     }
10085
10086   /* ... and now, if we're doing the mergeinfo thang, we execute a
10087      pair of record-only merges using the real sources we've
10088      calculated.
10089
10090      Issue #3648: We don't actually perform these two record-only merges
10091      on the WC at first, but rather see what each would do and store that
10092      in two mergeinfo catalogs.  We then merge the catalogs together and
10093      then record the result in the WC.  This prevents the second record
10094      only merge from removing legitimate mergeinfo history, from the same
10095      source, that was made in prior merges. */
10096   if (same_repos && !dry_run)
10097     {
10098       svn_mergeinfo_catalog_t add_result_catalog =
10099         apr_hash_make(scratch_pool);
10100       svn_mergeinfo_catalog_t remove_result_catalog =
10101         apr_hash_make(scratch_pool);
10102
10103       notify_mergeinfo_recording(target->abspath, NULL, ctx, scratch_pool);
10104       svn_pool_clear(subpool);
10105       SVN_ERR(do_merge(NULL, add_result_catalog, conflict_report, use_sleep,
10106                        add_sources, target,
10107                        URL1_ra_session, TRUE, same_repos,
10108                        FALSE /*ignore_mergeinfo*/, diff_ignore_ancestry,
10109                        force_delete, dry_run, TRUE,
10110                        modified_subtrees, TRUE,
10111                        TRUE, depth, merge_options, ctx,
10112                        scratch_pool, subpool));
10113       if (*conflict_report)
10114         {
10115           *conflict_report = conflict_report_dup(*conflict_report, result_pool);
10116           if (! (*conflict_report)->was_last_range)
10117             return SVN_NO_ERROR;
10118         }
10119       svn_pool_clear(subpool);
10120       SVN_ERR(do_merge(NULL, remove_result_catalog, conflict_report, use_sleep,
10121                        remove_sources, target,
10122                        URL1_ra_session, TRUE, same_repos,
10123                        FALSE /*ignore_mergeinfo*/, diff_ignore_ancestry,
10124                        force_delete, dry_run, TRUE,
10125                        modified_subtrees, TRUE,
10126                        TRUE, depth, merge_options, ctx,
10127                        scratch_pool, subpool));
10128       if (*conflict_report)
10129         {
10130           *conflict_report = conflict_report_dup(*conflict_report, result_pool);
10131           if (! (*conflict_report)->was_last_range)
10132             return SVN_NO_ERROR;
10133         }
10134       SVN_ERR(svn_mergeinfo_catalog_merge(add_result_catalog,
10135                                           remove_result_catalog,
10136                                           scratch_pool, scratch_pool));
10137       SVN_ERR(svn_client__record_wc_mergeinfo_catalog(add_result_catalog,
10138                                                       ctx, scratch_pool));
10139     }
10140
10141   svn_pool_destroy(subpool);
10142   return SVN_NO_ERROR;
10143 }
10144
10145 /* Perform checks to determine whether the working copy at TARGET_ABSPATH
10146  * can safely be used as a merge target. Checks are performed according to
10147  * the ALLOW_MIXED_REV, ALLOW_LOCAL_MODS, and ALLOW_SWITCHED_SUBTREES
10148  * parameters. If any checks fail, raise SVN_ERR_CLIENT_NOT_READY_TO_MERGE.
10149  *
10150  * E.g. if all the ALLOW_* parameters are FALSE, TARGET_ABSPATH must
10151  * be a single-revision, pristine, unswitched working copy.
10152  * In other words, it must reflect a subtree of the repository as found
10153  * at single revision -- although sparse checkouts are permitted. */
10154 static svn_error_t *
10155 ensure_wc_is_suitable_merge_target(const char *target_abspath,
10156                                    svn_client_ctx_t *ctx,
10157                                    svn_boolean_t allow_mixed_rev,
10158                                    svn_boolean_t allow_local_mods,
10159                                    svn_boolean_t allow_switched_subtrees,
10160                                    apr_pool_t *scratch_pool)
10161 {
10162   svn_node_kind_t target_kind;
10163
10164   /* Check the target exists. */
10165   SVN_ERR(svn_io_check_path(target_abspath, &target_kind, scratch_pool));
10166   if (target_kind == svn_node_none)
10167     return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
10168                              _("Path '%s' does not exist"),
10169                              svn_dirent_local_style(target_abspath,
10170                                                     scratch_pool));
10171   SVN_ERR(svn_wc_read_kind2(&target_kind, ctx->wc_ctx, target_abspath,
10172                             FALSE, FALSE, scratch_pool));
10173   if (target_kind != svn_node_dir && target_kind != svn_node_file)
10174     return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
10175                              _("Merge target '%s' does not exist in the "
10176                                "working copy"), target_abspath);
10177
10178   /* Perform the mixed-revision check first because it's the cheapest one. */
10179   if (! allow_mixed_rev)
10180     {
10181       svn_revnum_t min_rev;
10182       svn_revnum_t max_rev;
10183
10184       SVN_ERR(svn_client_min_max_revisions(&min_rev, &max_rev, target_abspath,
10185                                            FALSE, ctx, scratch_pool));
10186
10187       if (!(SVN_IS_VALID_REVNUM(min_rev) && SVN_IS_VALID_REVNUM(max_rev)))
10188         {
10189           svn_boolean_t is_added;
10190
10191           /* Allow merge into added nodes. */
10192           SVN_ERR(svn_wc__node_is_added(&is_added, ctx->wc_ctx, target_abspath,
10193                                         scratch_pool));
10194           if (is_added)
10195             return SVN_NO_ERROR;
10196           else
10197             return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
10198                                     _("Cannot determine revision of working "
10199                                       "copy"));
10200         }
10201
10202       if (min_rev != max_rev)
10203         return svn_error_createf(SVN_ERR_CLIENT_MERGE_UPDATE_REQUIRED, NULL,
10204                                  _("Cannot merge into mixed-revision working "
10205                                    "copy [%ld:%ld]; try updating first"),
10206                                    min_rev, max_rev);
10207     }
10208
10209   /* Next, check for switched subtrees. */
10210   if (! allow_switched_subtrees)
10211     {
10212       svn_boolean_t is_switched;
10213
10214       SVN_ERR(svn_wc__has_switched_subtrees(&is_switched, ctx->wc_ctx,
10215                                             target_abspath, NULL,
10216                                             scratch_pool));
10217       if (is_switched)
10218         return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
10219                                 _("Cannot merge into a working copy "
10220                                   "with a switched subtree"));
10221     }
10222
10223   /* This is the most expensive check, so it is performed last.*/
10224   if (! allow_local_mods)
10225     {
10226       svn_boolean_t is_modified;
10227
10228       SVN_ERR(svn_wc__has_local_mods(&is_modified, ctx->wc_ctx,
10229                                      target_abspath,
10230                                      ctx->cancel_func,
10231                                      ctx->cancel_baton,
10232                                      scratch_pool));
10233       if (is_modified)
10234         return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
10235                                 _("Cannot merge into a working copy "
10236                                   "that has local modifications"));
10237     }
10238
10239   return SVN_NO_ERROR;
10240 }
10241
10242 /* Throw an error if PATH_OR_URL is a path and REVISION isn't a repository
10243  * revision. */
10244 static svn_error_t *
10245 ensure_wc_path_has_repo_revision(const char *path_or_url,
10246                                  const svn_opt_revision_t *revision,
10247                                  apr_pool_t *scratch_pool)
10248 {
10249   if (revision->kind != svn_opt_revision_number
10250       && revision->kind != svn_opt_revision_date
10251       && revision->kind != svn_opt_revision_head
10252       && ! svn_path_is_url(path_or_url))
10253     return svn_error_createf(
10254       SVN_ERR_CLIENT_BAD_REVISION, NULL,
10255       _("Invalid merge source '%s'; a working copy path can only be "
10256         "used with a repository revision (a number, a date, or head)"),
10257       svn_dirent_local_style(path_or_url, scratch_pool));
10258   return SVN_NO_ERROR;
10259 }
10260
10261 /* "Open" the target WC for a merge.  That means:
10262  *   - find out its exact repository location
10263  *   - check the WC for suitability (throw an error if unsuitable)
10264  *
10265  * Set *TARGET_P to a new, fully initialized, target description structure.
10266  *
10267  * ALLOW_MIXED_REV, ALLOW_LOCAL_MODS, ALLOW_SWITCHED_SUBTREES determine
10268  * whether the WC is deemed suitable; see ensure_wc_is_suitable_merge_target()
10269  * for details.
10270  *
10271  * If the node is locally added, the rev and URL will be null/invalid. Some
10272  * kinds of merge can use such a target; others can't.
10273  */
10274 static svn_error_t *
10275 open_target_wc(merge_target_t **target_p,
10276                const char *wc_abspath,
10277                svn_boolean_t allow_mixed_rev,
10278                svn_boolean_t allow_local_mods,
10279                svn_boolean_t allow_switched_subtrees,
10280                svn_client_ctx_t *ctx,
10281                apr_pool_t *result_pool,
10282                apr_pool_t *scratch_pool)
10283 {
10284   merge_target_t *target = apr_palloc(result_pool, sizeof(*target));
10285   svn_client__pathrev_t *origin;
10286
10287   target->abspath = apr_pstrdup(result_pool, wc_abspath);
10288
10289   SVN_ERR(svn_client__wc_node_get_origin(&origin, wc_abspath, ctx,
10290                                          result_pool, scratch_pool));
10291   if (origin)
10292     {
10293       target->loc = *origin;
10294     }
10295   else
10296     {
10297       svn_error_t *err;
10298       /* The node has no location in the repository. It's unversioned or
10299        * locally added or locally deleted.
10300        *
10301        * If it's locally added or deleted, find the repository root
10302        * URL and UUID anyway, and leave the node URL and revision as NULL
10303        * and INVALID.  If it's unversioned, this will throw an error. */
10304       err = svn_wc__node_get_repos_info(NULL, NULL,
10305                                         &target->loc.repos_root_url,
10306                                         &target->loc.repos_uuid,
10307                                         ctx->wc_ctx, wc_abspath,
10308                                         result_pool, scratch_pool);
10309
10310       if (err)
10311         {
10312           if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND
10313               && err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY
10314               && err->apr_err != SVN_ERR_WC_UPGRADE_REQUIRED)
10315             return svn_error_trace(err);
10316
10317           return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, err,
10318                                    _("Merge target '%s' does not exist in the "
10319                                      "working copy"),
10320                                    svn_dirent_local_style(wc_abspath,
10321                                                           scratch_pool));
10322         }
10323
10324       target->loc.rev = SVN_INVALID_REVNUM;
10325       target->loc.url = NULL;
10326     }
10327
10328   SVN_ERR(ensure_wc_is_suitable_merge_target(
10329             wc_abspath, ctx,
10330             allow_mixed_rev, allow_local_mods, allow_switched_subtrees,
10331             scratch_pool));
10332
10333   *target_p = target;
10334   return SVN_NO_ERROR;
10335 }
10336
10337 /*-----------------------------------------------------------------------*/
10338 \f
10339 /*** Public APIs ***/
10340
10341 /* The body of svn_client_merge5(), which see for details.
10342  *
10343  * If SOURCE1 @ REVISION1 is related to SOURCE2 @ REVISION2 then use merge
10344  * tracking (subject to other constraints -- see HONOR_MERGEINFO());
10345  * otherwise disable merge tracking.
10346  *
10347  * IGNORE_MERGEINFO and DIFF_IGNORE_ANCESTRY are as in do_merge().
10348  */
10349 static svn_error_t *
10350 merge_locked(conflict_report_t **conflict_report,
10351              const char *source1,
10352              const svn_opt_revision_t *revision1,
10353              const char *source2,
10354              const svn_opt_revision_t *revision2,
10355              const char *target_abspath,
10356              svn_depth_t depth,
10357              svn_boolean_t ignore_mergeinfo,
10358              svn_boolean_t diff_ignore_ancestry,
10359              svn_boolean_t force_delete,
10360              svn_boolean_t record_only,
10361              svn_boolean_t dry_run,
10362              svn_boolean_t allow_mixed_rev,
10363              const apr_array_header_t *merge_options,
10364              svn_client_ctx_t *ctx,
10365              apr_pool_t *result_pool,
10366              apr_pool_t *scratch_pool)
10367 {
10368   merge_target_t *target;
10369   svn_client__pathrev_t *source1_loc, *source2_loc;
10370   svn_boolean_t sources_related = FALSE;
10371   svn_ra_session_t *ra_session1, *ra_session2;
10372   apr_array_header_t *merge_sources;
10373   svn_error_t *err;
10374   svn_boolean_t use_sleep = FALSE;
10375   svn_client__pathrev_t *yca = NULL;
10376   apr_pool_t *sesspool;
10377   svn_boolean_t same_repos;
10378
10379   /* ### FIXME: This function really ought to do a history check on
10380      the left and right sides of the merge source, and -- if one is an
10381      ancestor of the other -- just call svn_client_merge_peg3() with
10382      the appropriate args. */
10383
10384   SVN_ERR(open_target_wc(&target, target_abspath,
10385                          allow_mixed_rev, TRUE, TRUE,
10386                          ctx, scratch_pool, scratch_pool));
10387
10388   /* Open RA sessions to both sides of our merge source, and resolve URLs
10389    * and revisions. */
10390   sesspool = svn_pool_create(scratch_pool);
10391   SVN_ERR(svn_client__ra_session_from_path2(
10392             &ra_session1, &source1_loc,
10393             source1, NULL, revision1, revision1, ctx, sesspool));
10394   SVN_ERR(svn_client__ra_session_from_path2(
10395             &ra_session2, &source2_loc,
10396             source2, NULL, revision2, revision2, ctx, sesspool));
10397
10398   /* We can't do a diff between different repositories. */
10399   /* ### We should also insist that the root URLs of the two sources match,
10400    *     as we are only carrying around a single source-repos-root from now
10401    *     on, and URL calculations will go wrong if they differ.
10402    *     Alternatively, teach the code to cope with differing root URLs. */
10403   SVN_ERR(check_same_repos(source1_loc, source1_loc->url,
10404                            source2_loc, source2_loc->url,
10405                            FALSE /* strict_urls */, scratch_pool));
10406
10407   /* Do our working copy and sources come from the same repository? */
10408   same_repos = is_same_repos(&target->loc, source1_loc, TRUE /* strict_urls */);
10409
10410   /* Unless we're ignoring ancestry, see if the two sources are related.  */
10411   if (! ignore_mergeinfo)
10412     SVN_ERR(svn_client__get_youngest_common_ancestor(
10413                     &yca, source1_loc, source2_loc, ra_session1, ctx,
10414                     scratch_pool, scratch_pool));
10415
10416   /* Check for a youngest common ancestor.  If we have one, we'll be
10417      doing merge tracking.
10418
10419      So, given a requested merge of the differences between A and
10420      B, and a common ancestor of C, we will find ourselves in one of
10421      four positions, and four different approaches:
10422
10423         A == B == C   there's nothing to merge
10424
10425         A == C != B   we merge the changes between A (or C) and B
10426
10427         B == C != A   we merge the changes between B (or C) and A
10428
10429         A != B != C   we merge the changes between A and B without
10430                       merge recording, then record-only two merges:
10431                       from A to C, and from C to B
10432   */
10433   if (yca)
10434     {
10435       /* Note that our merge sources are related. */
10436       sources_related = TRUE;
10437
10438       /* If the common ancestor matches the right side of our merge,
10439          then we only need to reverse-merge the left side. */
10440       if ((strcmp(yca->url, source2_loc->url) == 0)
10441           && (yca->rev == source2_loc->rev))
10442         {
10443           SVN_ERR(normalize_merge_sources_internal(
10444                     &merge_sources, source1_loc,
10445                     svn_rangelist__initialize(source1_loc->rev, yca->rev, TRUE,
10446                                               scratch_pool),
10447                     ra_session1, ctx, scratch_pool, scratch_pool));
10448         }
10449       /* If the common ancestor matches the left side of our merge,
10450          then we only need to merge the right side. */
10451       else if ((strcmp(yca->url, source1_loc->url) == 0)
10452                && (yca->rev == source1_loc->rev))
10453         {
10454           SVN_ERR(normalize_merge_sources_internal(
10455                     &merge_sources, source2_loc,
10456                     svn_rangelist__initialize(yca->rev, source2_loc->rev, TRUE,
10457                                               scratch_pool),
10458                     ra_session2, ctx, scratch_pool, scratch_pool));
10459         }
10460       /* And otherwise, we need to do both: reverse merge the left
10461          side, and merge the right. */
10462       else
10463         {
10464           merge_source_t source;
10465
10466           source.loc1 = source1_loc;
10467           source.loc2 = source2_loc;
10468           source.ancestral = FALSE;
10469
10470           err = merge_cousins_and_supplement_mergeinfo(conflict_report,
10471                                                        &use_sleep,
10472                                                        target,
10473                                                        ra_session1,
10474                                                        ra_session2,
10475                                                        &source,
10476                                                        yca,
10477                                                        same_repos,
10478                                                        depth,
10479                                                        diff_ignore_ancestry,
10480                                                        force_delete,
10481                                                        record_only, dry_run,
10482                                                        merge_options,
10483                                                        ctx,
10484                                                        result_pool,
10485                                                        scratch_pool);
10486           /* Close our temporary RA sessions (this could've happened
10487              after the second call to normalize_merge_sources() inside
10488              the merge_cousins_and_supplement_mergeinfo() routine). */
10489           svn_pool_destroy(sesspool);
10490
10491           if (use_sleep)
10492             svn_io_sleep_for_timestamps(target->abspath, scratch_pool);
10493
10494           SVN_ERR(err);
10495           return SVN_NO_ERROR;
10496         }
10497     }
10498   else
10499     {
10500       /* Build a single-item merge_source_t array. */
10501       merge_sources = apr_array_make(scratch_pool, 1, sizeof(merge_source_t *));
10502       APR_ARRAY_PUSH(merge_sources, merge_source_t *)
10503         = merge_source_create(source1_loc, source2_loc, FALSE, scratch_pool);
10504     }
10505
10506   err = do_merge(NULL, NULL, conflict_report, &use_sleep,
10507                  merge_sources, target,
10508                  ra_session1, sources_related, same_repos,
10509                  ignore_mergeinfo, diff_ignore_ancestry, force_delete, dry_run,
10510                  record_only, NULL, FALSE, FALSE, depth, merge_options,
10511                  ctx, result_pool, scratch_pool);
10512
10513   /* Close our temporary RA sessions. */
10514   svn_pool_destroy(sesspool);
10515
10516   if (use_sleep)
10517     svn_io_sleep_for_timestamps(target->abspath, scratch_pool);
10518
10519   SVN_ERR(err);
10520   return SVN_NO_ERROR;
10521 }
10522
10523 /* Set *TARGET_ABSPATH to the absolute path of, and *LOCK_ABSPATH to
10524  the absolute path to lock for, TARGET_WCPATH. */
10525 static svn_error_t *
10526 get_target_and_lock_abspath(const char **target_abspath,
10527                             const char **lock_abspath,
10528                             const char *target_wcpath,
10529                             svn_client_ctx_t *ctx,
10530                             apr_pool_t *result_pool)
10531 {
10532   svn_node_kind_t kind;
10533   SVN_ERR(svn_dirent_get_absolute(target_abspath, target_wcpath,
10534                                   result_pool));
10535   SVN_ERR(svn_wc_read_kind2(&kind, ctx->wc_ctx, *target_abspath,
10536                             FALSE, FALSE, result_pool));
10537   if (kind == svn_node_dir)
10538     *lock_abspath = *target_abspath;
10539   else
10540     *lock_abspath = svn_dirent_dirname(*target_abspath, result_pool);
10541
10542   return SVN_NO_ERROR;
10543 }
10544
10545 svn_error_t *
10546 svn_client_merge5(const char *source1,
10547                   const svn_opt_revision_t *revision1,
10548                   const char *source2,
10549                   const svn_opt_revision_t *revision2,
10550                   const char *target_wcpath,
10551                   svn_depth_t depth,
10552                   svn_boolean_t ignore_mergeinfo,
10553                   svn_boolean_t diff_ignore_ancestry,
10554                   svn_boolean_t force_delete,
10555                   svn_boolean_t record_only,
10556                   svn_boolean_t dry_run,
10557                   svn_boolean_t allow_mixed_rev,
10558                   const apr_array_header_t *merge_options,
10559                   svn_client_ctx_t *ctx,
10560                   apr_pool_t *pool)
10561 {
10562   const char *target_abspath, *lock_abspath;
10563   conflict_report_t *conflict_report;
10564
10565   /* Sanity check our input -- we require specified revisions,
10566    * and either 2 paths or 2 URLs. */
10567   if ((revision1->kind == svn_opt_revision_unspecified)
10568       || (revision2->kind == svn_opt_revision_unspecified))
10569     return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL,
10570                             _("Not all required revisions are specified"));
10571   if (svn_path_is_url(source1) != svn_path_is_url(source2))
10572     return svn_error_create(SVN_ERR_ILLEGAL_TARGET, NULL,
10573                             _("Merge sources must both be "
10574                               "either paths or URLs"));
10575   /* A WC path must be used with a repository revision, as we can't
10576    * (currently) use the WC itself as a source, we can only read the URL
10577    * from it and use that. */
10578   SVN_ERR(ensure_wc_path_has_repo_revision(source1, revision1, pool));
10579   SVN_ERR(ensure_wc_path_has_repo_revision(source2, revision2, pool));
10580
10581   SVN_ERR(get_target_and_lock_abspath(&target_abspath, &lock_abspath,
10582                                       target_wcpath, ctx, pool));
10583
10584   if (!dry_run)
10585     SVN_WC__CALL_WITH_WRITE_LOCK(
10586       merge_locked(&conflict_report,
10587                    source1, revision1, source2, revision2,
10588                    target_abspath, depth, ignore_mergeinfo,
10589                    diff_ignore_ancestry,
10590                    force_delete, record_only, dry_run,
10591                    allow_mixed_rev, merge_options, ctx, pool, pool),
10592       ctx->wc_ctx, lock_abspath, FALSE /* lock_anchor */, pool);
10593   else
10594     SVN_ERR(merge_locked(&conflict_report,
10595                    source1, revision1, source2, revision2,
10596                    target_abspath, depth, ignore_mergeinfo,
10597                    diff_ignore_ancestry,
10598                    force_delete, record_only, dry_run,
10599                    allow_mixed_rev, merge_options, ctx, pool, pool));
10600
10601   SVN_ERR(make_merge_conflict_error(conflict_report, pool));
10602   return SVN_NO_ERROR;
10603 }
10604
10605
10606 /* Check if mergeinfo for a given path is described explicitly or via
10607    inheritance in a mergeinfo catalog.
10608
10609    If REPOS_REL_PATH exists in CATALOG and has mergeinfo containing
10610    MERGEINFO, then set *IN_CATALOG to TRUE.  If REPOS_REL_PATH does
10611    not exist in CATALOG, then find its nearest parent which does exist.
10612    If the mergeinfo REPOS_REL_PATH would inherit from that parent
10613    contains MERGEINFO then set *IN_CATALOG to TRUE.  Set *IN_CATALOG
10614    to FALSE in all other cases.
10615
10616    Set *CAT_KEY_PATH to the key path in CATALOG for REPOS_REL_PATH's
10617    explicit or inherited mergeinfo.  If no explicit or inherited mergeinfo
10618    is found for REPOS_REL_PATH then set *CAT_KEY_PATH to NULL.
10619
10620    User RESULT_POOL to allocate *CAT_KEY_PATH.  Use SCRATCH_POOL for
10621    temporary allocations. */
10622 static svn_error_t *
10623 mergeinfo_in_catalog(svn_boolean_t *in_catalog,
10624                      const char **cat_key_path,
10625                      const char *repos_rel_path,
10626                      svn_mergeinfo_t mergeinfo,
10627                      svn_mergeinfo_catalog_t catalog,
10628                      apr_pool_t *result_pool,
10629                      apr_pool_t *scratch_pool)
10630 {
10631   const char *walk_path = NULL;
10632
10633   *in_catalog = FALSE;
10634   *cat_key_path = NULL;
10635
10636   if (mergeinfo && catalog && apr_hash_count(catalog))
10637     {
10638       const char *path = repos_rel_path;
10639
10640       /* Start with the assumption there is no explicit or inherited
10641          mergeinfo for REPOS_REL_PATH in CATALOG. */
10642       svn_mergeinfo_t mergeinfo_in_cat = NULL;
10643
10644       while (1)
10645         {
10646           mergeinfo_in_cat = svn_hash_gets(catalog, path);
10647
10648           if (mergeinfo_in_cat) /* Found it! */
10649             {
10650               *cat_key_path = apr_pstrdup(result_pool, path);
10651               break;
10652             }
10653           else /* Look for inherited mergeinfo. */
10654             {
10655               walk_path = svn_relpath_join(svn_relpath_basename(path,
10656                                                                 scratch_pool),
10657                                            walk_path ? walk_path : "",
10658                                            scratch_pool);
10659               path = svn_relpath_dirname(path, scratch_pool);
10660
10661               if (path[0] == '\0') /* No mergeinfo to inherit. */
10662                 break;
10663             }
10664         }
10665
10666       if (mergeinfo_in_cat)
10667         {
10668           if (walk_path)
10669             SVN_ERR(svn_mergeinfo__add_suffix_to_mergeinfo(&mergeinfo_in_cat,
10670                                                            mergeinfo_in_cat,
10671                                                            walk_path,
10672                                                            scratch_pool,
10673                                                            scratch_pool));
10674           SVN_ERR(svn_mergeinfo_intersect2(&mergeinfo_in_cat,
10675                                            mergeinfo_in_cat, mergeinfo,
10676                                            TRUE,
10677                                            scratch_pool, scratch_pool));
10678           SVN_ERR(svn_mergeinfo__equals(in_catalog, mergeinfo_in_cat,
10679                                         mergeinfo, TRUE, scratch_pool));
10680         }
10681     }
10682
10683   return SVN_NO_ERROR;
10684 }
10685
10686 /* A svn_log_entry_receiver_t baton for log_find_operative_revs(). */
10687 typedef struct log_find_operative_baton_t
10688 {
10689   /* The catalog of explicit mergeinfo on a reintegrate source. */
10690   svn_mergeinfo_catalog_t merged_catalog;
10691
10692   /* The catalog of unmerged history from the reintegrate target to
10693      the source which we will create.  Allocated in RESULT_POOL. */
10694   svn_mergeinfo_catalog_t unmerged_catalog;
10695
10696   /* The repository absolute path of the reintegrate target. */
10697   const char *target_fspath;
10698
10699   /* The path of the reintegrate source relative to the repository root. */
10700   const char *source_repos_rel_path;
10701
10702   apr_pool_t *result_pool;
10703 } log_find_operative_baton_t;
10704
10705 /* A svn_log_entry_receiver_t callback for find_unsynced_ranges(). */
10706 static svn_error_t *
10707 log_find_operative_revs(void *baton,
10708                         svn_log_entry_t *log_entry,
10709                         apr_pool_t *pool)
10710 {
10711   log_find_operative_baton_t *log_baton = baton;
10712   apr_hash_index_t *hi;
10713   svn_revnum_t revision;
10714
10715   /* It's possible that authz restrictions on the merge source prevent us
10716      from knowing about any of the changes for LOG_ENTRY->REVISION. */
10717   if (!log_entry->changed_paths2)
10718     return SVN_NO_ERROR;
10719
10720   revision = log_entry->revision;
10721
10722   for (hi = apr_hash_first(pool, log_entry->changed_paths2);
10723        hi;
10724        hi = apr_hash_next(hi))
10725     {
10726       const char *subtree_missing_this_rev;
10727       const char *path = svn__apr_hash_index_key(hi);
10728       const char *rel_path;
10729       const char *source_rel_path;
10730       svn_boolean_t in_catalog;
10731       svn_mergeinfo_t log_entry_as_mergeinfo;
10732
10733       rel_path = svn_fspath__skip_ancestor(log_baton->target_fspath, path);
10734       /* Easy out: The path is not within the tree of interest. */
10735       if (rel_path == NULL)
10736         continue;
10737
10738       source_rel_path = svn_relpath_join(log_baton->source_repos_rel_path,
10739                                          rel_path, pool);
10740
10741       SVN_ERR(svn_mergeinfo_parse(&log_entry_as_mergeinfo,
10742                                   apr_psprintf(pool, "%s:%ld",
10743                                                path, revision),
10744                                   pool));
10745
10746       SVN_ERR(mergeinfo_in_catalog(&in_catalog, &subtree_missing_this_rev,
10747                                    source_rel_path, log_entry_as_mergeinfo,
10748                                    log_baton->merged_catalog,
10749                                    pool, pool));
10750
10751       if (!in_catalog)
10752         {
10753           svn_mergeinfo_t unmerged_for_key;
10754           const char *suffix, *missing_path;
10755
10756           /* If there is no mergeinfo on the source tree we'll say
10757              the "subtree" missing this revision is the root of the
10758              source. */
10759           if (!subtree_missing_this_rev)
10760             subtree_missing_this_rev = log_baton->source_repos_rel_path;
10761
10762           suffix = svn_relpath_skip_ancestor(subtree_missing_this_rev,
10763                                              source_rel_path);
10764           if (suffix && suffix[0] != '\0')
10765             {
10766               missing_path = apr_pstrmemdup(pool, path,
10767                                             strlen(path) - strlen(suffix) - 1);
10768             }
10769           else
10770             {
10771               missing_path = path;
10772             }
10773
10774           SVN_ERR(svn_mergeinfo_parse(&log_entry_as_mergeinfo,
10775                                       apr_psprintf(pool, "%s:%ld",
10776                                                    missing_path, revision),
10777                                       log_baton->result_pool));
10778           unmerged_for_key = svn_hash_gets(log_baton->unmerged_catalog,
10779                                            subtree_missing_this_rev);
10780
10781           if (unmerged_for_key)
10782             {
10783               SVN_ERR(svn_mergeinfo_merge2(unmerged_for_key,
10784                                            log_entry_as_mergeinfo,
10785                                            log_baton->result_pool,
10786                                            pool));
10787             }
10788           else
10789             {
10790               svn_hash_sets(log_baton->unmerged_catalog,
10791                             apr_pstrdup(log_baton->result_pool,
10792                                         subtree_missing_this_rev),
10793                             log_entry_as_mergeinfo);
10794             }
10795
10796         }
10797     }
10798   return SVN_NO_ERROR;
10799 }
10800
10801 /* Determine if the mergeinfo on a reintegrate source SOURCE_LOC,
10802    reflects that the source is fully synced with the reintegrate target
10803    TARGET_LOC, even if a naive interpretation of the source's
10804    mergeinfo says otherwise -- See issue #3577.
10805
10806    UNMERGED_CATALOG represents the history (as mergeinfo) from
10807    TARGET_LOC that is not represented in SOURCE_LOC's
10808    explicit/inherited mergeinfo as represented by MERGED_CATALOG.
10809    MERGED_CATALOG may be empty if the source has no explicit or inherited
10810    mergeinfo.
10811
10812    Check that all of the unmerged revisions in UNMERGED_CATALOG's
10813    mergeinfos are "phantoms", that is, one of the following conditions holds:
10814
10815      1) The revision affects no corresponding paths in SOURCE_LOC.
10816
10817      2) The revision affects corresponding paths in SOURCE_LOC,
10818         but based on the mergeinfo in MERGED_CATALOG, the change was
10819         previously merged.
10820
10821    Make a deep copy, allocated in RESULT_POOL, of any portions of
10822    UNMERGED_CATALOG that are not phantoms, to TRUE_UNMERGED_CATALOG.
10823
10824    Note: The keys in all mergeinfo catalogs used here are relative to the
10825    root of the repository.
10826
10827    RA_SESSION is an RA session open to the repository of TARGET_LOC; it may
10828    be temporarily reparented within this function.
10829
10830    Use SCRATCH_POOL for all temporary allocations. */
10831 static svn_error_t *
10832 find_unsynced_ranges(const svn_client__pathrev_t *source_loc,
10833                      const svn_client__pathrev_t *target_loc,
10834                      svn_mergeinfo_catalog_t unmerged_catalog,
10835                      svn_mergeinfo_catalog_t merged_catalog,
10836                      svn_mergeinfo_catalog_t true_unmerged_catalog,
10837                      svn_ra_session_t *ra_session,
10838                      apr_pool_t *result_pool,
10839                      apr_pool_t *scratch_pool)
10840 {
10841   svn_rangelist_t *potentially_unmerged_ranges = NULL;
10842
10843   /* Convert all the unmerged history to a rangelist. */
10844   if (apr_hash_count(unmerged_catalog))
10845     {
10846       apr_hash_index_t *hi_catalog;
10847
10848       potentially_unmerged_ranges =
10849         apr_array_make(scratch_pool, 1, sizeof(svn_merge_range_t *));
10850
10851       for (hi_catalog = apr_hash_first(scratch_pool, unmerged_catalog);
10852            hi_catalog;
10853            hi_catalog = apr_hash_next(hi_catalog))
10854         {
10855           svn_mergeinfo_t mergeinfo = svn__apr_hash_index_val(hi_catalog);
10856
10857           SVN_ERR(svn_rangelist__merge_many(potentially_unmerged_ranges,
10858                                             mergeinfo,
10859                                             scratch_pool, scratch_pool));
10860         }
10861     }
10862
10863   /* Find any unmerged revisions which both affect the source and
10864      are not yet merged to it. */
10865   if (potentially_unmerged_ranges)
10866     {
10867       svn_revnum_t oldest_rev =
10868         (APR_ARRAY_IDX(potentially_unmerged_ranges,
10869                        0,
10870                        svn_merge_range_t *))->start + 1;
10871       svn_revnum_t youngest_rev =
10872         (APR_ARRAY_IDX(potentially_unmerged_ranges,
10873                        potentially_unmerged_ranges->nelts - 1,
10874                        svn_merge_range_t *))->end;
10875       log_find_operative_baton_t log_baton;
10876       const char *old_session_url;
10877       svn_error_t *err;
10878
10879       log_baton.merged_catalog = merged_catalog;
10880       log_baton.unmerged_catalog = true_unmerged_catalog;
10881       log_baton.source_repos_rel_path
10882         = svn_client__pathrev_relpath(source_loc, scratch_pool);
10883       log_baton.target_fspath
10884         = svn_client__pathrev_fspath(target_loc, scratch_pool);
10885       log_baton.result_pool = result_pool;
10886
10887       SVN_ERR(svn_client__ensure_ra_session_url(
10888                 &old_session_url, ra_session, target_loc->url, scratch_pool));
10889       err = get_log(ra_session, "", youngest_rev, oldest_rev,
10890                     TRUE, /* discover_changed_paths */
10891                     log_find_operative_revs, &log_baton,
10892                     scratch_pool);
10893       SVN_ERR(svn_error_compose_create(
10894                 err, svn_ra_reparent(ra_session, old_session_url, scratch_pool)));
10895     }
10896
10897   return SVN_NO_ERROR;
10898 }
10899
10900
10901 /* Find the youngest revision that has been merged from target to source.
10902  *
10903  * If any location in TARGET_HISTORY_AS_MERGEINFO is mentioned in
10904  * SOURCE_MERGEINFO, then we know that at least one merge was done from the
10905  * target to the source.  In that case, set *YOUNGEST_MERGED_REV to the
10906  * youngest revision of that intersection (unless *YOUNGEST_MERGED_REV is
10907  * already younger than that).  Otherwise, leave *YOUNGEST_MERGED_REV alone.
10908  */
10909 static svn_error_t *
10910 find_youngest_merged_rev(svn_revnum_t *youngest_merged_rev,
10911                          svn_mergeinfo_t target_history_as_mergeinfo,
10912                          svn_mergeinfo_t source_mergeinfo,
10913                          apr_pool_t *scratch_pool)
10914 {
10915   svn_mergeinfo_t explicit_source_target_history_intersection;
10916
10917   SVN_ERR(svn_mergeinfo_intersect2(
10918             &explicit_source_target_history_intersection,
10919             source_mergeinfo, target_history_as_mergeinfo, TRUE,
10920             scratch_pool, scratch_pool));
10921   if (apr_hash_count(explicit_source_target_history_intersection))
10922     {
10923       svn_revnum_t old_rev, young_rev;
10924
10925       /* Keep track of the youngest revision merged from target to source. */
10926       SVN_ERR(svn_mergeinfo__get_range_endpoints(
10927                 &young_rev, &old_rev,
10928                 explicit_source_target_history_intersection, scratch_pool));
10929       if (!SVN_IS_VALID_REVNUM(*youngest_merged_rev)
10930           || (young_rev > *youngest_merged_rev))
10931         *youngest_merged_rev = young_rev;
10932     }
10933
10934   return SVN_NO_ERROR;
10935 }
10936
10937 /* Set *FILTERED_MERGEINFO_P to the parts of TARGET_HISTORY_AS_MERGEINFO
10938  * that are not present in the source branch.
10939  *
10940  * SOURCE_MERGEINFO is the explicit or inherited mergeinfo of the source
10941  * branch SOURCE_PATHREV.  Extend SOURCE_MERGEINFO, modifying it in
10942  * place, to include the natural history (implicit mergeinfo) of
10943  * SOURCE_PATHREV.  ### But make these additions in SCRATCH_POOL.
10944  *
10945  * SOURCE_RA_SESSION is an RA session open to the repository containing
10946  * SOURCE_PATHREV; it may be temporarily reparented within this function.
10947  *
10948  * ### [JAF] This function is named '..._subroutine' simply because I
10949  *     factored it out based on code similarity, without knowing what it's
10950  *     purpose is.  We should clarify its purpose and choose a better name.
10951  */
10952 static svn_error_t *
10953 find_unmerged_mergeinfo_subroutine(svn_mergeinfo_t *filtered_mergeinfo_p,
10954                                    svn_mergeinfo_t target_history_as_mergeinfo,
10955                                    svn_mergeinfo_t source_mergeinfo,
10956                                    const svn_client__pathrev_t *source_pathrev,
10957                                    svn_ra_session_t *source_ra_session,
10958                                    svn_client_ctx_t *ctx,
10959                                    apr_pool_t *result_pool,
10960                                    apr_pool_t *scratch_pool)
10961 {
10962   svn_mergeinfo_t source_history_as_mergeinfo;
10963
10964   /* Get the source path's natural history and merge it into source
10965      path's explicit or inherited mergeinfo. */
10966   SVN_ERR(svn_client__get_history_as_mergeinfo(
10967             &source_history_as_mergeinfo, NULL /* has_rev_zero_history */,
10968             source_pathrev, source_pathrev->rev, SVN_INVALID_REVNUM,
10969             source_ra_session, ctx, scratch_pool));
10970   SVN_ERR(svn_mergeinfo_merge2(source_mergeinfo,
10971                                source_history_as_mergeinfo,
10972                                scratch_pool, scratch_pool));
10973
10974   /* Now source_mergeinfo represents everything we know about
10975      source_path's history.  Now we need to know what part, if any, of the
10976      corresponding target's history is *not* part of source_path's total
10977      history; because it is neither shared history nor was it ever merged
10978      from the target to the source. */
10979   SVN_ERR(svn_mergeinfo_remove2(filtered_mergeinfo_p,
10980                                 source_mergeinfo,
10981                                 target_history_as_mergeinfo, TRUE,
10982                                 result_pool, scratch_pool));
10983   return SVN_NO_ERROR;
10984 }
10985
10986 /* Helper for calculate_left_hand_side() which produces a mergeinfo catalog
10987    describing what parts of of the reintegrate target have not previously been
10988    merged to the reintegrate source.
10989
10990    SOURCE_CATALOG is the collection of explicit mergeinfo on SOURCE_LOC and
10991    all its children, i.e. the mergeinfo catalog for the reintegrate source.
10992
10993    TARGET_HISTORY_HASH is a hash of (const char *) paths mapped to
10994    svn_mergeinfo_t representing the location history.  Each of these
10995    path keys represent a path in the reintegrate target, relative to the
10996    repository root, which has explicit mergeinfo and/or is the reintegrate
10997    target itself.  The svn_mergeinfo_t's contain the natural history of each
10998    path@TARGET_REV.  Effectively this is the mergeinfo catalog on the
10999    reintegrate target.
11000
11001    YC_ANCESTOR_REV is the revision of the youngest common ancestor of the
11002    reintegrate source and the reintegrate target.
11003
11004    SOURCE_LOC is the reintegrate source.
11005
11006    SOURCE_RA_SESSION is a session opened to the URL of SOURCE_LOC
11007    and TARGET_RA_SESSION is open to TARGET->loc.url.
11008
11009    For each entry in TARGET_HISTORY_HASH check that the history it
11010    represents is contained in either the explicit mergeinfo for the
11011    corresponding path in SOURCE_CATALOG, the corresponding path's inherited
11012    mergeinfo (if no explicit mergeinfo for the path is found in
11013    SOURCE_CATALOG), or the corresponding path's natural history.  Populate
11014    *UNMERGED_TO_SOURCE_CATALOG with the corresponding source paths mapped to
11015    the mergeinfo from the target's natural history which is *not* found.  Also
11016    include any mergeinfo from SOURCE_CATALOG which explicitly describes the
11017    target's history but for which *no* entry was found in
11018    TARGET_HISTORY_HASH.
11019
11020    If no part of TARGET_HISTORY_HASH is found in SOURCE_CATALOG set
11021    *YOUNGEST_MERGED_REV to SVN_INVALID_REVNUM; otherwise set it to the youngest
11022    revision previously merged from the target to the source, and filter
11023    *UNMERGED_TO_SOURCE_CATALOG so that it contains no ranges greater than
11024    *YOUNGEST_MERGED_REV.
11025
11026    *UNMERGED_TO_SOURCE_CATALOG is (deeply) allocated in RESULT_POOL.
11027    SCRATCH_POOL is used for all temporary allocations.  */
11028 static svn_error_t *
11029 find_unmerged_mergeinfo(svn_mergeinfo_catalog_t *unmerged_to_source_catalog,
11030                         svn_revnum_t *youngest_merged_rev,
11031                         svn_revnum_t yc_ancestor_rev,
11032                         svn_mergeinfo_catalog_t source_catalog,
11033                         apr_hash_t *target_history_hash,
11034                         const svn_client__pathrev_t *source_loc,
11035                         const merge_target_t *target,
11036                         svn_ra_session_t *source_ra_session,
11037                         svn_ra_session_t *target_ra_session,
11038                         svn_client_ctx_t *ctx,
11039                         apr_pool_t *result_pool,
11040                         apr_pool_t *scratch_pool)
11041 {
11042   const char *source_repos_rel_path
11043     = svn_client__pathrev_relpath(source_loc, scratch_pool);
11044   const char *target_repos_rel_path
11045     = svn_client__pathrev_relpath(&target->loc, scratch_pool);
11046   apr_hash_index_t *hi;
11047   svn_mergeinfo_catalog_t new_catalog = apr_hash_make(result_pool);
11048   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
11049
11050   assert(session_url_is(source_ra_session, source_loc->url, scratch_pool));
11051   assert(session_url_is(target_ra_session, target->loc.url, scratch_pool));
11052
11053   *youngest_merged_rev = SVN_INVALID_REVNUM;
11054
11055   /* Examine the natural history of each path in the reintegrate target
11056      with explicit mergeinfo. */
11057   for (hi = apr_hash_first(scratch_pool, target_history_hash);
11058        hi;
11059        hi = apr_hash_next(hi))
11060     {
11061       const char *target_path = svn__apr_hash_index_key(hi);
11062       svn_mergeinfo_t target_history_as_mergeinfo = svn__apr_hash_index_val(hi);
11063       const char *path_rel_to_session
11064         = svn_relpath_skip_ancestor(target_repos_rel_path, target_path);
11065       const char *source_path;
11066       svn_client__pathrev_t *source_pathrev;
11067       svn_mergeinfo_t source_mergeinfo, filtered_mergeinfo;
11068
11069       svn_pool_clear(iterpool);
11070
11071       source_path = svn_relpath_join(source_repos_rel_path,
11072                                      path_rel_to_session, iterpool);
11073       source_pathrev = svn_client__pathrev_join_relpath(
11074                          source_loc, path_rel_to_session, iterpool);
11075
11076       /* Remove any target history that is also part of the source's history,
11077          i.e. their common ancestry.  By definition this has already been
11078          "merged" from the target to the source.  If the source has explicit
11079          self referential mergeinfo it would intersect with the target's
11080          history below, making it appear that some merges had been done from
11081          the target to the source, when this might not actually be the case. */
11082       SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
11083         &target_history_as_mergeinfo, target_history_as_mergeinfo,
11084         source_loc->rev, yc_ancestor_rev, TRUE, iterpool, iterpool));
11085
11086       /* Look for any explicit mergeinfo on the source path corresponding to
11087          the target path.  If we find any remove that from SOURCE_CATALOG.
11088          When this iteration over TARGET_HISTORY_HASH is complete all that
11089          should be left in SOURCE_CATALOG are subtrees that have explicit
11090          mergeinfo on the reintegrate source where there is no corresponding
11091          explicit mergeinfo on the reintegrate target. */
11092       source_mergeinfo = svn_hash_gets(source_catalog, source_path);
11093       if (source_mergeinfo)
11094         {
11095           svn_hash_sets(source_catalog, source_path, NULL);
11096
11097           SVN_ERR(find_youngest_merged_rev(youngest_merged_rev,
11098                                            target_history_as_mergeinfo,
11099                                            source_mergeinfo,
11100                                            iterpool));
11101         }
11102       else
11103         {
11104           /* There is no mergeinfo on source_path *or* source_path doesn't
11105              exist at all.  If simply doesn't exist we can ignore it
11106              altogether. */
11107           svn_node_kind_t kind;
11108
11109           SVN_ERR(svn_ra_check_path(source_ra_session,
11110                                     path_rel_to_session,
11111                                     source_loc->rev, &kind, iterpool));
11112           if (kind == svn_node_none)
11113               continue;
11114           /* Else source_path does exist though it has no explicit mergeinfo.
11115              Find its inherited mergeinfo.  If it doesn't have any then simply
11116              set source_mergeinfo to an empty hash. */
11117           SVN_ERR(svn_client__get_repos_mergeinfo(
11118                     &source_mergeinfo, source_ra_session,
11119                     source_pathrev->url, source_pathrev->rev,
11120                     svn_mergeinfo_inherited, FALSE /*squelch_incapable*/,
11121                     iterpool));
11122           if (!source_mergeinfo)
11123             source_mergeinfo = apr_hash_make(iterpool);
11124         }
11125
11126       /* Use scratch_pool rather than iterpool because filtered_mergeinfo
11127          is going into new_catalog below and needs to last to the end of
11128          this function. */
11129       SVN_ERR(find_unmerged_mergeinfo_subroutine(
11130                 &filtered_mergeinfo, target_history_as_mergeinfo,
11131                 source_mergeinfo, source_pathrev,
11132                 source_ra_session, ctx, scratch_pool, iterpool));
11133       svn_hash_sets(new_catalog, apr_pstrdup(scratch_pool, source_path),
11134                     filtered_mergeinfo);
11135     }
11136
11137   /* Are there any subtrees with explicit mergeinfo still left in the merge
11138      source where there was no explicit mergeinfo for the corresponding path
11139      in the merge target?  If so, add the intersection of those path's
11140      mergeinfo and the corresponding target path's mergeinfo to
11141      new_catalog. */
11142   for (hi = apr_hash_first(scratch_pool, source_catalog);
11143        hi;
11144        hi = apr_hash_next(hi))
11145     {
11146       const char *source_path = svn__apr_hash_index_key(hi);
11147       const char *path_rel_to_session =
11148         svn_relpath_skip_ancestor(source_repos_rel_path, source_path);
11149       const char *source_url;
11150       svn_mergeinfo_t source_mergeinfo = svn__apr_hash_index_val(hi);
11151       svn_mergeinfo_t filtered_mergeinfo;
11152       svn_client__pathrev_t *target_pathrev;
11153       svn_mergeinfo_t target_history_as_mergeinfo;
11154       svn_error_t *err;
11155
11156       svn_pool_clear(iterpool);
11157
11158       source_url = svn_path_url_add_component2(source_loc->url,
11159                                                path_rel_to_session, iterpool);
11160       target_pathrev = svn_client__pathrev_join_relpath(
11161                          &target->loc, path_rel_to_session, iterpool);
11162       err = svn_client__get_history_as_mergeinfo(&target_history_as_mergeinfo,
11163                                                  NULL /* has_rev_zero_history */,
11164                                                  target_pathrev,
11165                                                  target->loc.rev,
11166                                                  SVN_INVALID_REVNUM,
11167                                                  target_ra_session,
11168                                                  ctx, iterpool);
11169       if (err)
11170         {
11171           if (err->apr_err == SVN_ERR_FS_NOT_FOUND
11172               || err->apr_err == SVN_ERR_RA_DAV_REQUEST_FAILED)
11173             {
11174               /* This path with explicit mergeinfo in the source doesn't
11175                  exist on the target. */
11176               svn_error_clear(err);
11177               err = NULL;
11178             }
11179           else
11180             {
11181               return svn_error_trace(err);
11182             }
11183         }
11184       else
11185         {
11186           svn_client__pathrev_t *pathrev;
11187
11188           SVN_ERR(find_youngest_merged_rev(youngest_merged_rev,
11189                                            target_history_as_mergeinfo,
11190                                            source_mergeinfo,
11191                                            iterpool));
11192
11193           /* Use scratch_pool rather than iterpool because filtered_mergeinfo
11194              is going into new_catalog below and needs to last to the end of
11195              this function. */
11196           /* ### Why looking at SOURCE_url at TARGET_rev? */
11197           SVN_ERR(svn_client__pathrev_create_with_session(
11198                     &pathrev, source_ra_session, target->loc.rev, source_url,
11199                     iterpool));
11200           SVN_ERR(find_unmerged_mergeinfo_subroutine(
11201                     &filtered_mergeinfo, target_history_as_mergeinfo,
11202                     source_mergeinfo, pathrev,
11203                     source_ra_session, ctx, scratch_pool, iterpool));
11204           if (apr_hash_count(filtered_mergeinfo))
11205             svn_hash_sets(new_catalog,
11206                           apr_pstrdup(scratch_pool, source_path),
11207                           filtered_mergeinfo);
11208         }
11209     }
11210
11211   /* Limit new_catalog to the youngest revisions previously merged from
11212      the target to the source. */
11213   if (SVN_IS_VALID_REVNUM(*youngest_merged_rev))
11214     SVN_ERR(svn_mergeinfo__filter_catalog_by_ranges(&new_catalog,
11215                                                     new_catalog,
11216                                                     *youngest_merged_rev,
11217                                                     0, /* No oldest bound. */
11218                                                     TRUE,
11219                                                     scratch_pool,
11220                                                     scratch_pool));
11221
11222   /* Make a shiny new copy before blowing away all the temporary pools. */
11223   *unmerged_to_source_catalog = svn_mergeinfo_catalog_dup(new_catalog,
11224                                                           result_pool);
11225   svn_pool_destroy(iterpool);
11226   return SVN_NO_ERROR;
11227 }
11228
11229 /* Helper for svn_client_merge_reintegrate() which calculates the
11230    'left hand side' of the underlying two-URL merge that a --reintegrate
11231    merge actually performs.  If no merge should be performed, set
11232    *LEFT_P to NULL.
11233
11234    TARGET->abspath is the absolute working copy path of the reintegrate
11235    merge.
11236
11237    SOURCE_LOC is the reintegrate source.
11238
11239    SUBTREES_WITH_MERGEINFO is a hash of (const char *) absolute paths mapped
11240    to (svn_mergeinfo_t *) mergeinfo values for each working copy path with
11241    explicit mergeinfo in TARGET->abspath.  Actually we only need to know the
11242    paths, not the mergeinfo.
11243
11244    TARGET->loc.rev is the working revision the entire WC tree rooted at
11245    TARGET is at.
11246
11247    Populate *UNMERGED_TO_SOURCE_CATALOG with the mergeinfo describing what
11248    parts of TARGET->loc have not been merged to SOURCE_LOC, up to the
11249    youngest revision ever merged from the TARGET->abspath to the source if
11250    such exists, see doc string for find_unmerged_mergeinfo().
11251
11252    SOURCE_RA_SESSION is a session opened to the SOURCE_LOC
11253    and TARGET_RA_SESSION is open to TARGET->loc.url.
11254
11255    *LEFT_P, *MERGED_TO_SOURCE_CATALOG , and *UNMERGED_TO_SOURCE_CATALOG are
11256    allocated in RESULT_POOL.  SCRATCH_POOL is used for all temporary
11257    allocations. */
11258 static svn_error_t *
11259 calculate_left_hand_side(svn_client__pathrev_t **left_p,
11260                          svn_mergeinfo_catalog_t *merged_to_source_catalog,
11261                          svn_mergeinfo_catalog_t *unmerged_to_source_catalog,
11262                          const merge_target_t *target,
11263                          apr_hash_t *subtrees_with_mergeinfo,
11264                          const svn_client__pathrev_t *source_loc,
11265                          svn_ra_session_t *source_ra_session,
11266                          svn_ra_session_t *target_ra_session,
11267                          svn_client_ctx_t *ctx,
11268                          apr_pool_t *result_pool,
11269                          apr_pool_t *scratch_pool)
11270 {
11271   svn_mergeinfo_catalog_t mergeinfo_catalog, unmerged_catalog;
11272   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
11273   apr_hash_index_t *hi;
11274   /* hash of paths mapped to arrays of svn_mergeinfo_t. */
11275   apr_hash_t *target_history_hash = apr_hash_make(scratch_pool);
11276   svn_revnum_t youngest_merged_rev;
11277   svn_client__pathrev_t *yc_ancestor;
11278
11279   assert(session_url_is(source_ra_session, source_loc->url, scratch_pool));
11280   assert(session_url_is(target_ra_session, target->loc.url, scratch_pool));
11281
11282   /* Initialize our return variables. */
11283   *left_p = NULL;
11284
11285   /* TARGET->abspath may not have explicit mergeinfo and thus may not be
11286      contained within SUBTREES_WITH_MERGEINFO.  If this is the case then
11287      add a dummy item for TARGET->abspath so we get its history (i.e. implicit
11288      mergeinfo) below.  */
11289   if (!svn_hash_gets(subtrees_with_mergeinfo, target->abspath))
11290     svn_hash_sets(subtrees_with_mergeinfo, target->abspath,
11291                   apr_hash_make(result_pool));
11292
11293   /* Get the history segments (as mergeinfo) for TARGET->abspath and any of
11294      its subtrees with explicit mergeinfo. */
11295   for (hi = apr_hash_first(scratch_pool, subtrees_with_mergeinfo);
11296        hi;
11297        hi = apr_hash_next(hi))
11298     {
11299       const char *local_abspath = svn__apr_hash_index_key(hi);
11300       svn_client__pathrev_t *target_child;
11301       const char *repos_relpath;
11302       svn_mergeinfo_t target_history_as_mergeinfo;
11303
11304       svn_pool_clear(iterpool);
11305
11306       /* Convert the absolute path with mergeinfo on it to a path relative
11307          to the session root. */
11308       SVN_ERR(svn_wc__node_get_repos_info(NULL, &repos_relpath, NULL, NULL,
11309                                           ctx->wc_ctx, local_abspath,
11310                                           scratch_pool, iterpool));
11311       target_child = svn_client__pathrev_create_with_relpath(
11312                        target->loc.repos_root_url, target->loc.repos_uuid,
11313                        target->loc.rev, repos_relpath, iterpool);
11314       SVN_ERR(svn_client__get_history_as_mergeinfo(&target_history_as_mergeinfo,
11315                                                    NULL /* has_rev_zero_hist */,
11316                                                    target_child,
11317                                                    target->loc.rev,
11318                                                    SVN_INVALID_REVNUM,
11319                                                    target_ra_session,
11320                                                    ctx, scratch_pool));
11321
11322       svn_hash_sets(target_history_hash, repos_relpath,
11323                     target_history_as_mergeinfo);
11324     }
11325
11326   /* Check that SOURCE_LOC and TARGET->loc are
11327      actually related, we can't reintegrate if they are not.  Also
11328      get an initial value for the YCA revision number. */
11329   SVN_ERR(svn_client__get_youngest_common_ancestor(
11330               &yc_ancestor, source_loc, &target->loc, target_ra_session, ctx,
11331               iterpool, iterpool));
11332   if (! yc_ancestor)
11333     return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
11334                              _("'%s@%ld' must be ancestrally related to "
11335                                "'%s@%ld'"), source_loc->url, source_loc->rev,
11336                              target->loc.url, target->loc.rev);
11337
11338   /* If the source revision is the same as the youngest common
11339      revision, then there can't possibly be any unmerged revisions
11340      that we need to apply to target. */
11341   if (source_loc->rev == yc_ancestor->rev)
11342     {
11343       svn_pool_destroy(iterpool);
11344       return SVN_NO_ERROR;
11345     }
11346
11347   /* Get the mergeinfo from the source, including its descendants
11348      with differing explicit mergeinfo. */
11349   SVN_ERR(svn_client__get_repos_mergeinfo_catalog(
11350             &mergeinfo_catalog, source_ra_session,
11351             source_loc->url, source_loc->rev,
11352             svn_mergeinfo_inherited, FALSE /* squelch_incapable */,
11353             TRUE /* include_descendants */, iterpool, iterpool));
11354
11355   if (!mergeinfo_catalog)
11356     mergeinfo_catalog = apr_hash_make(iterpool);
11357
11358   *merged_to_source_catalog = svn_mergeinfo_catalog_dup(mergeinfo_catalog,
11359                                                         result_pool);
11360
11361   /* Filter the source's mergeinfo catalog so that we are left with
11362      mergeinfo that describes what has *not* previously been merged from
11363      TARGET->loc to SOURCE_LOC. */
11364   SVN_ERR(find_unmerged_mergeinfo(&unmerged_catalog,
11365                                   &youngest_merged_rev,
11366                                   yc_ancestor->rev,
11367                                   mergeinfo_catalog,
11368                                   target_history_hash,
11369                                   source_loc,
11370                                   target,
11371                                   source_ra_session,
11372                                   target_ra_session,
11373                                   ctx,
11374                                   iterpool, iterpool));
11375
11376   /* Simplify unmerged_catalog through elision then make a copy in POOL. */
11377   SVN_ERR(svn_client__elide_mergeinfo_catalog(unmerged_catalog,
11378                                               iterpool));
11379   *unmerged_to_source_catalog = svn_mergeinfo_catalog_dup(unmerged_catalog,
11380                                                           result_pool);
11381
11382   if (youngest_merged_rev == SVN_INVALID_REVNUM)
11383     {
11384       /* We never merged to the source.  Just return the branch point. */
11385       *left_p = svn_client__pathrev_dup(yc_ancestor, result_pool);
11386     }
11387   else
11388     {
11389       /* We've previously merged some or all of the target, up to
11390          youngest_merged_rev, to the source.  Set
11391          *LEFT_P to cover the youngest part of this range. */
11392       SVN_ERR(svn_client__repos_location(left_p, target_ra_session,
11393                                          &target->loc, youngest_merged_rev,
11394                                          ctx, result_pool, iterpool));
11395     }
11396
11397   svn_pool_destroy(iterpool);
11398   return SVN_NO_ERROR;
11399 }
11400
11401 /* Determine the URLs and revisions needed to perform a reintegrate merge
11402  * from SOURCE_LOC into the working copy at TARGET.
11403  *
11404  * SOURCE_RA_SESSION and TARGET_RA_SESSION are RA sessions opened to the
11405  * URLs of SOURCE_LOC and TARGET->loc respectively.
11406  *
11407  * Set *SOURCE_P to
11408  * the source-left and source-right locations of the required merge.  Set
11409  * *YC_ANCESTOR_P to the location of the youngest ancestor.
11410  * Any of these output pointers may be NULL if not wanted.
11411  *
11412  * See svn_client_find_reintegrate_merge() for other details.
11413  */
11414 static svn_error_t *
11415 find_reintegrate_merge(merge_source_t **source_p,
11416                        svn_client__pathrev_t **yc_ancestor_p,
11417                        svn_ra_session_t *source_ra_session,
11418                        const svn_client__pathrev_t *source_loc,
11419                        svn_ra_session_t *target_ra_session,
11420                        const merge_target_t *target,
11421                        svn_client_ctx_t *ctx,
11422                        apr_pool_t *result_pool,
11423                        apr_pool_t *scratch_pool)
11424 {
11425   svn_client__pathrev_t *yc_ancestor;
11426   svn_client__pathrev_t *loc1;
11427   merge_source_t source;
11428   svn_mergeinfo_catalog_t unmerged_to_source_mergeinfo_catalog;
11429   svn_mergeinfo_catalog_t merged_to_source_mergeinfo_catalog;
11430   svn_error_t *err;
11431   apr_hash_t *subtrees_with_mergeinfo;
11432
11433   assert(session_url_is(source_ra_session, source_loc->url, scratch_pool));
11434   assert(session_url_is(target_ra_session, target->loc.url, scratch_pool));
11435
11436   /* As the WC tree is "pure", use its last-updated-to revision as
11437      the default revision for the left side of our merge, since that's
11438      what the repository sub-tree is required to be up to date with
11439      (with regard to the WC). */
11440   /* ### Bogus/obsolete comment? */
11441
11442   /* Can't reintegrate to or from the root of the repository. */
11443   if (strcmp(source_loc->url, source_loc->repos_root_url) == 0
11444       || strcmp(target->loc.url, target->loc.repos_root_url) == 0)
11445     return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
11446                              _("Neither the reintegrate source nor target "
11447                                "can be the root of the repository"));
11448
11449   /* Find all the subtrees in TARGET_WCPATH that have explicit mergeinfo. */
11450   err = get_wc_explicit_mergeinfo_catalog(&subtrees_with_mergeinfo,
11451                                           target->abspath, svn_depth_infinity,
11452                                           ctx, scratch_pool, scratch_pool);
11453   /* Issue #3896: If invalid mergeinfo in the reintegrate target
11454      prevents us from proceeding, then raise the best error possible. */
11455   if (err && err->apr_err == SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING)
11456     err = svn_error_quick_wrap(err, _("Reintegrate merge not possible"));
11457   SVN_ERR(err);
11458
11459   SVN_ERR(calculate_left_hand_side(&loc1,
11460                                    &merged_to_source_mergeinfo_catalog,
11461                                    &unmerged_to_source_mergeinfo_catalog,
11462                                    target,
11463                                    subtrees_with_mergeinfo,
11464                                    source_loc,
11465                                    source_ra_session,
11466                                    target_ra_session,
11467                                    ctx,
11468                                    scratch_pool, scratch_pool));
11469
11470   /* Did calculate_left_hand_side() decide that there was no merge to
11471      be performed here?  */
11472   if (! loc1)
11473     {
11474       if (source_p)
11475         *source_p = NULL;
11476       if (yc_ancestor_p)
11477         *yc_ancestor_p = NULL;
11478       return SVN_NO_ERROR;
11479     }
11480
11481   source.loc1 = loc1;
11482   source.loc2 = source_loc;
11483
11484   /* If the target was moved after the source was branched from it,
11485      it is possible that the left URL differs from the target's current
11486      URL.  If so, then adjust TARGET_RA_SESSION to point to the old URL. */
11487   if (strcmp(source.loc1->url, target->loc.url))
11488     SVN_ERR(svn_ra_reparent(target_ra_session, source.loc1->url, scratch_pool));
11489
11490   SVN_ERR(svn_client__get_youngest_common_ancestor(
11491             &yc_ancestor, source.loc2, source.loc1, target_ra_session,
11492             ctx, scratch_pool, scratch_pool));
11493
11494   if (! yc_ancestor)
11495     return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
11496                              _("'%s@%ld' must be ancestrally related to "
11497                                "'%s@%ld'"),
11498                              source.loc1->url, source.loc1->rev,
11499                              source.loc2->url, source.loc2->rev);
11500
11501   /* The source side of a reintegrate merge is not 'ancestral', except in
11502    * the degenerate case where source == YCA. */
11503   source.ancestral = (loc1->rev == yc_ancestor->rev);
11504
11505   if (source.loc1->rev > yc_ancestor->rev)
11506     {
11507       /* Have we actually merged anything to the source from the
11508          target?  If so, make sure we've merged a contiguous
11509          prefix. */
11510       svn_mergeinfo_catalog_t final_unmerged_catalog = apr_hash_make(scratch_pool);
11511
11512       SVN_ERR(find_unsynced_ranges(source_loc, &target->loc,
11513                                    unmerged_to_source_mergeinfo_catalog,
11514                                    merged_to_source_mergeinfo_catalog,
11515                                    final_unmerged_catalog,
11516                                    target_ra_session, scratch_pool,
11517                                    scratch_pool));
11518
11519       if (apr_hash_count(final_unmerged_catalog))
11520         {
11521           svn_string_t *source_mergeinfo_cat_string;
11522
11523           SVN_ERR(svn_mergeinfo__catalog_to_formatted_string(
11524             &source_mergeinfo_cat_string,
11525             final_unmerged_catalog,
11526             "  ", "    Missing ranges: ", scratch_pool));
11527           return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE,
11528                                    NULL,
11529                                    _("Reintegrate can only be used if "
11530                                      "revisions %ld through %ld were "
11531                                      "previously merged from %s to the "
11532                                      "reintegrate source, but this is "
11533                                      "not the case:\n%s"),
11534                                    yc_ancestor->rev + 1, source.loc2->rev,
11535                                    target->loc.url,
11536                                    source_mergeinfo_cat_string->data);
11537         }
11538     }
11539
11540   /* Left side: trunk@youngest-trunk-rev-merged-to-branch-at-specified-peg-rev
11541    * Right side: branch@specified-peg-revision */
11542   if (source_p)
11543     *source_p = merge_source_dup(&source, result_pool);
11544
11545   if (yc_ancestor_p)
11546     *yc_ancestor_p = svn_client__pathrev_dup(yc_ancestor, result_pool);
11547   return SVN_NO_ERROR;
11548 }
11549
11550 /* Resolve the source and target locations and open RA sessions to them, and
11551  * perform some checks appropriate for a reintegrate merge.
11552  *
11553  * Set *SOURCE_RA_SESSION_P and *SOURCE_LOC_P to a new session and the
11554  * repository location of SOURCE_PATH_OR_URL at SOURCE_PEG_REVISION.  Set
11555  * *TARGET_RA_SESSION_P and *TARGET_P to a new session and the repository
11556  * location of the WC at TARGET_ABSPATH.
11557  *
11558  * Throw a SVN_ERR_CLIENT_UNRELATED_RESOURCES error if the target WC node is
11559  * a locally added node or if the source and target are not in the same
11560  * repository.  Throw a SVN_ERR_CLIENT_NOT_READY_TO_MERGE error if the
11561  * target WC is not at a single revision without switched subtrees and
11562  * without local mods.
11563  *
11564  * Allocate all the outputs in RESULT_POOL.
11565  */
11566 static svn_error_t *
11567 open_reintegrate_source_and_target(svn_ra_session_t **source_ra_session_p,
11568                                    svn_client__pathrev_t **source_loc_p,
11569                                    svn_ra_session_t **target_ra_session_p,
11570                                    merge_target_t **target_p,
11571                                    const char *source_path_or_url,
11572                                    const svn_opt_revision_t *source_peg_revision,
11573                                    const char *target_abspath,
11574                                    svn_client_ctx_t *ctx,
11575                                    apr_pool_t *result_pool,
11576                                    apr_pool_t *scratch_pool)
11577 {
11578   svn_client__pathrev_t *source_loc;
11579   merge_target_t *target;
11580
11581   /* Open the target WC.  A reintegrate merge requires the merge target to
11582    * reflect a subtree of the repository as found at a single revision. */
11583   SVN_ERR(open_target_wc(&target, target_abspath,
11584                          FALSE, FALSE, FALSE,
11585                          ctx, scratch_pool, scratch_pool));
11586   SVN_ERR(svn_client_open_ra_session2(target_ra_session_p,
11587                                       target->loc.url, target->abspath,
11588                                       ctx, result_pool, scratch_pool));
11589   if (! target->loc.url)
11590     return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
11591                              _("Can't reintegrate into '%s' because it is "
11592                                "locally added and therefore not related to "
11593                                "the merge source"),
11594                              svn_dirent_local_style(target->abspath,
11595                                                     scratch_pool));
11596
11597   SVN_ERR(svn_client__ra_session_from_path2(
11598             source_ra_session_p, &source_loc,
11599             source_path_or_url, NULL, source_peg_revision, source_peg_revision,
11600             ctx, result_pool));
11601
11602   /* source_loc and target->loc are required to be in the same repository,
11603      as mergeinfo doesn't come into play for cross-repository merging. */
11604   SVN_ERR(check_same_repos(source_loc,
11605                            svn_dirent_local_style(source_path_or_url,
11606                                                   scratch_pool),
11607                            &target->loc,
11608                            svn_dirent_local_style(target->abspath,
11609                                                   scratch_pool),
11610                            TRUE /* strict_urls */, scratch_pool));
11611
11612   *source_loc_p = source_loc;
11613   *target_p = target;
11614   return SVN_NO_ERROR;
11615 }
11616
11617 /* The body of svn_client_merge_reintegrate(), which see for details. */
11618 static svn_error_t *
11619 merge_reintegrate_locked(conflict_report_t **conflict_report,
11620                          const char *source_path_or_url,
11621                          const svn_opt_revision_t *source_peg_revision,
11622                          const char *target_abspath,
11623                          svn_boolean_t diff_ignore_ancestry,
11624                          svn_boolean_t dry_run,
11625                          const apr_array_header_t *merge_options,
11626                          svn_client_ctx_t *ctx,
11627                          apr_pool_t *result_pool,
11628                          apr_pool_t *scratch_pool)
11629 {
11630   svn_ra_session_t *target_ra_session, *source_ra_session;
11631   merge_target_t *target;
11632   svn_client__pathrev_t *source_loc;
11633   merge_source_t *source;
11634   svn_client__pathrev_t *yc_ancestor;
11635   svn_boolean_t use_sleep = FALSE;
11636   svn_error_t *err;
11637
11638   SVN_ERR(open_reintegrate_source_and_target(
11639             &source_ra_session, &source_loc, &target_ra_session, &target,
11640             source_path_or_url, source_peg_revision, target_abspath,
11641             ctx, scratch_pool, scratch_pool));
11642
11643   SVN_ERR(find_reintegrate_merge(&source, &yc_ancestor,
11644                                  source_ra_session, source_loc,
11645                                  target_ra_session, target,
11646                                  ctx, scratch_pool, scratch_pool));
11647
11648   if (! source)
11649     {
11650       return SVN_NO_ERROR;
11651     }
11652
11653   /* Do the real merge! */
11654   /* ### TODO(reint): Make sure that one isn't the same line ancestor
11655      ### of the other (what's erroneously referred to as "ancestrally
11656      ### related" in this source file).  For now, we just say the source
11657      ### isn't "ancestral" even if it is (in the degenerate case where
11658      ### source-left equals YCA). */
11659   source->ancestral = FALSE;
11660   err = merge_cousins_and_supplement_mergeinfo(conflict_report,
11661                                                &use_sleep,
11662                                                target,
11663                                                target_ra_session,
11664                                                source_ra_session,
11665                                                source, yc_ancestor,
11666                                                TRUE /* same_repos */,
11667                                                svn_depth_infinity,
11668                                                diff_ignore_ancestry,
11669                                                FALSE /* force_delete */,
11670                                                FALSE /* record_only */,
11671                                                dry_run,
11672                                                merge_options,
11673                                                ctx,
11674                                                result_pool, scratch_pool);
11675
11676   if (use_sleep)
11677     svn_io_sleep_for_timestamps(target_abspath, scratch_pool);
11678
11679   SVN_ERR(err);
11680   return SVN_NO_ERROR;
11681 }
11682
11683 svn_error_t *
11684 svn_client_merge_reintegrate(const char *source_path_or_url,
11685                              const svn_opt_revision_t *source_peg_revision,
11686                              const char *target_wcpath,
11687                              svn_boolean_t dry_run,
11688                              const apr_array_header_t *merge_options,
11689                              svn_client_ctx_t *ctx,
11690                              apr_pool_t *pool)
11691 {
11692   const char *target_abspath, *lock_abspath;
11693   conflict_report_t *conflict_report;
11694
11695   SVN_ERR(get_target_and_lock_abspath(&target_abspath, &lock_abspath,
11696                                       target_wcpath, ctx, pool));
11697
11698   if (!dry_run)
11699     SVN_WC__CALL_WITH_WRITE_LOCK(
11700       merge_reintegrate_locked(&conflict_report,
11701                                source_path_or_url, source_peg_revision,
11702                                target_abspath,
11703                                FALSE /*diff_ignore_ancestry*/,
11704                                dry_run, merge_options, ctx, pool, pool),
11705       ctx->wc_ctx, lock_abspath, FALSE /* lock_anchor */, pool);
11706   else
11707     SVN_ERR(merge_reintegrate_locked(&conflict_report,
11708                                      source_path_or_url, source_peg_revision,
11709                                      target_abspath,
11710                                      FALSE /*diff_ignore_ancestry*/,
11711                                      dry_run, merge_options, ctx, pool, pool));
11712
11713   SVN_ERR(make_merge_conflict_error(conflict_report, pool));
11714   return SVN_NO_ERROR;
11715 }
11716
11717
11718 /* The body of svn_client_merge_peg5(), which see for details.
11719  *
11720  * IGNORE_MERGEINFO and DIFF_IGNORE_ANCESTRY are as in do_merge().
11721  */
11722 static svn_error_t *
11723 merge_peg_locked(conflict_report_t **conflict_report,
11724                  const char *source_path_or_url,
11725                  const svn_opt_revision_t *source_peg_revision,
11726                  const svn_rangelist_t *ranges_to_merge,
11727                  const char *target_abspath,
11728                  svn_depth_t depth,
11729                  svn_boolean_t ignore_mergeinfo,
11730                  svn_boolean_t diff_ignore_ancestry,
11731                  svn_boolean_t force_delete,
11732                  svn_boolean_t record_only,
11733                  svn_boolean_t dry_run,
11734                  svn_boolean_t allow_mixed_rev,
11735                  const apr_array_header_t *merge_options,
11736                  svn_client_ctx_t *ctx,
11737                  apr_pool_t *result_pool,
11738                  apr_pool_t *scratch_pool)
11739 {
11740   merge_target_t *target;
11741   svn_client__pathrev_t *source_loc;
11742   apr_array_header_t *merge_sources;
11743   svn_ra_session_t *ra_session;
11744   apr_pool_t *sesspool;
11745   svn_boolean_t use_sleep = FALSE;
11746   svn_error_t *err;
11747   svn_boolean_t same_repos;
11748
11749   SVN_ERR_ASSERT(svn_dirent_is_absolute(target_abspath));
11750
11751   SVN_ERR(open_target_wc(&target, target_abspath,
11752                          allow_mixed_rev, TRUE, TRUE,
11753                          ctx, scratch_pool, scratch_pool));
11754
11755   /* Create a short lived session pool */
11756   sesspool = svn_pool_create(scratch_pool);
11757
11758   /* Open an RA session to our source URL, and determine its root URL. */
11759   SVN_ERR(svn_client__ra_session_from_path2(
11760             &ra_session, &source_loc,
11761             source_path_or_url, NULL, source_peg_revision, source_peg_revision,
11762             ctx, sesspool));
11763
11764   /* Normalize our merge sources. */
11765   SVN_ERR(normalize_merge_sources(&merge_sources, source_path_or_url,
11766                                   source_loc,
11767                                   ranges_to_merge, ra_session, ctx,
11768                                   scratch_pool, scratch_pool));
11769
11770   /* Check for same_repos. */
11771   same_repos = is_same_repos(&target->loc, source_loc, TRUE /* strict_urls */);
11772
11773   /* Do the real merge!  (We say with confidence that our merge
11774      sources are both ancestral and related.) */
11775   err = do_merge(NULL, NULL, conflict_report, &use_sleep,
11776                  merge_sources, target, ra_session,
11777                  TRUE /*sources_related*/, same_repos, ignore_mergeinfo,
11778                  diff_ignore_ancestry, force_delete, dry_run,
11779                  record_only, NULL, FALSE, FALSE, depth, merge_options,
11780                  ctx, result_pool, scratch_pool);
11781
11782   /* We're done with our RA session. */
11783   svn_pool_destroy(sesspool);
11784
11785   if (use_sleep)
11786     svn_io_sleep_for_timestamps(target_abspath, scratch_pool);
11787
11788   SVN_ERR(err);
11789   return SVN_NO_ERROR;
11790 }
11791
11792 /* Details of an automatic merge. */
11793 typedef struct automatic_merge_t
11794 {
11795   svn_client__pathrev_t *yca, *base, *right, *target;
11796   svn_boolean_t is_reintegrate_like;
11797   svn_boolean_t allow_mixed_rev, allow_local_mods, allow_switched_subtrees;
11798 } automatic_merge_t;
11799
11800 static svn_error_t *
11801 client_find_automatic_merge(automatic_merge_t **merge_p,
11802                             const char *source_path_or_url,
11803                             const svn_opt_revision_t *source_revision,
11804                             const char *target_abspath,
11805                             svn_boolean_t allow_mixed_rev,
11806                             svn_boolean_t allow_local_mods,
11807                             svn_boolean_t allow_switched_subtrees,
11808                             svn_client_ctx_t *ctx,
11809                             apr_pool_t *result_pool,
11810                             apr_pool_t *scratch_pool);
11811
11812 static svn_error_t *
11813 do_automatic_merge_locked(conflict_report_t **conflict_report,
11814                           const automatic_merge_t *merge,
11815                           const char *target_abspath,
11816                           svn_depth_t depth,
11817                           svn_boolean_t diff_ignore_ancestry,
11818                           svn_boolean_t force_delete,
11819                           svn_boolean_t record_only,
11820                           svn_boolean_t dry_run,
11821                           const apr_array_header_t *merge_options,
11822                           svn_client_ctx_t *ctx,
11823                           apr_pool_t *result_pool,
11824                           apr_pool_t *scratch_pool);
11825
11826 svn_error_t *
11827 svn_client_merge_peg5(const char *source_path_or_url,
11828                       const apr_array_header_t *ranges_to_merge,
11829                       const svn_opt_revision_t *source_peg_revision,
11830                       const char *target_wcpath,
11831                       svn_depth_t depth,
11832                       svn_boolean_t ignore_mergeinfo,
11833                       svn_boolean_t diff_ignore_ancestry,
11834                       svn_boolean_t force_delete,
11835                       svn_boolean_t record_only,
11836                       svn_boolean_t dry_run,
11837                       svn_boolean_t allow_mixed_rev,
11838                       const apr_array_header_t *merge_options,
11839                       svn_client_ctx_t *ctx,
11840                       apr_pool_t *pool)
11841 {
11842   const char *target_abspath, *lock_abspath;
11843   conflict_report_t *conflict_report;
11844
11845   /* No ranges to merge?  No problem. */
11846   if (ranges_to_merge != NULL && ranges_to_merge->nelts == 0)
11847     return SVN_NO_ERROR;
11848
11849   SVN_ERR(get_target_and_lock_abspath(&target_abspath, &lock_abspath,
11850                                       target_wcpath, ctx, pool));
11851
11852   /* Do an automatic merge if no revision ranges are specified. */
11853   if (ranges_to_merge == NULL)
11854     {
11855       automatic_merge_t *merge;
11856
11857       if (ignore_mergeinfo)
11858         return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
11859                                 _("Cannot merge automatically while "
11860                                   "ignoring mergeinfo"));
11861
11862       /* Find the details of the merge needed. */
11863       SVN_ERR(client_find_automatic_merge(
11864                                     &merge,
11865                                     source_path_or_url, source_peg_revision,
11866                                     target_abspath,
11867                                     allow_mixed_rev,
11868                                     TRUE /*allow_local_mods*/,
11869                                     TRUE /*allow_switched_subtrees*/,
11870                                     ctx, pool, pool));
11871
11872       if (!dry_run)
11873         SVN_WC__CALL_WITH_WRITE_LOCK(
11874           do_automatic_merge_locked(&conflict_report,
11875                                     merge,
11876                                     target_abspath, depth,
11877                                     diff_ignore_ancestry,
11878                                     force_delete, record_only, dry_run,
11879                                     merge_options, ctx, pool, pool),
11880           ctx->wc_ctx, lock_abspath, FALSE /* lock_anchor */, pool);
11881       else
11882         SVN_ERR(do_automatic_merge_locked(&conflict_report,
11883                                     merge,
11884                                     target_abspath, depth,
11885                                     diff_ignore_ancestry,
11886                                     force_delete, record_only, dry_run,
11887                                     merge_options, ctx, pool, pool));
11888     }
11889   else if (!dry_run)
11890     SVN_WC__CALL_WITH_WRITE_LOCK(
11891       merge_peg_locked(&conflict_report,
11892                        source_path_or_url, source_peg_revision,
11893                        ranges_to_merge,
11894                        target_abspath, depth, ignore_mergeinfo,
11895                        diff_ignore_ancestry,
11896                        force_delete, record_only, dry_run,
11897                        allow_mixed_rev, merge_options, ctx, pool, pool),
11898       ctx->wc_ctx, lock_abspath, FALSE /* lock_anchor */, pool);
11899   else
11900     SVN_ERR(merge_peg_locked(&conflict_report,
11901                        source_path_or_url, source_peg_revision,
11902                        ranges_to_merge,
11903                        target_abspath, depth, ignore_mergeinfo,
11904                        diff_ignore_ancestry,
11905                        force_delete, record_only, dry_run,
11906                        allow_mixed_rev, merge_options, ctx, pool, pool));
11907
11908   SVN_ERR(make_merge_conflict_error(conflict_report, pool));
11909   return SVN_NO_ERROR;
11910 }
11911
11912
11913 /* The location-history of a branch.
11914  *
11915  * This structure holds the set of path-revisions occupied by a branch,
11916  * from an externally chosen 'tip' location back to its origin.  The
11917  * 'tip' location is the youngest location that we are considering on
11918  * the branch. */
11919 typedef struct branch_history_t
11920 {
11921   /* The tip location of the branch.  That is, the youngest location that's
11922    * in the repository and that we're considering.  If we're considering a
11923    * target branch right up to an uncommitted WC, then this is the WC base
11924    * (pristine) location. */
11925   svn_client__pathrev_t *tip;
11926   /* The location-segment history, as mergeinfo. */
11927   svn_mergeinfo_t history;
11928   /* Whether the location-segment history reached as far as (necessarily
11929      the root path in) revision 0 -- a fact that can't be represented as
11930      mergeinfo. */
11931   svn_boolean_t has_r0_history;
11932 } branch_history_t;
11933
11934 /* Return the location on BRANCH_HISTORY at revision REV, or NULL if none. */
11935 static svn_client__pathrev_t *
11936 location_on_branch_at_rev(const branch_history_t *branch_history,
11937                           svn_revnum_t rev,
11938                           apr_pool_t *result_pool,
11939                           apr_pool_t *scratch_pool)
11940 {
11941   apr_hash_index_t *hi;
11942
11943   for (hi = apr_hash_first(scratch_pool, branch_history->history); hi;
11944        hi = apr_hash_next(hi))
11945     {
11946       const char *fspath = svn__apr_hash_index_key(hi);
11947       svn_rangelist_t *rangelist = svn__apr_hash_index_val(hi);
11948       int i;
11949
11950       for (i = 0; i < rangelist->nelts; i++)
11951         {
11952           svn_merge_range_t *r = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
11953           if (r->start < rev && rev <= r->end)
11954             {
11955               return svn_client__pathrev_create_with_relpath(
11956                        branch_history->tip->repos_root_url,
11957                        branch_history->tip->repos_uuid,
11958                        rev, fspath + 1, result_pool);
11959             }
11960         }
11961     }
11962   return NULL;
11963 }
11964
11965 /* */
11966 typedef struct source_and_target_t
11967 {
11968   svn_client__pathrev_t *source;
11969   svn_ra_session_t *source_ra_session;
11970   branch_history_t source_branch;
11971
11972   merge_target_t *target;
11973   svn_ra_session_t *target_ra_session;
11974   branch_history_t target_branch;
11975
11976   /* Repos location of the youngest common ancestor of SOURCE and TARGET. */
11977   svn_client__pathrev_t *yca;
11978 } source_and_target_t;
11979
11980 /* Set *INTERSECTION_P to the intersection of BRANCH_HISTORY with the
11981  * revision range OLDEST_REV to YOUNGEST_REV (inclusive).
11982  *
11983  * If the intersection is empty, the result will be a branch history object
11984  * containing an empty (not null) history.
11985  *
11986  * ### The 'tip' of the result is currently unchanged.
11987  */
11988 static svn_error_t *
11989 branch_history_intersect_range(branch_history_t **intersection_p,
11990                                const branch_history_t *branch_history,
11991                                svn_revnum_t oldest_rev,
11992                                svn_revnum_t youngest_rev,
11993                                apr_pool_t *result_pool,
11994                                apr_pool_t *scratch_pool)
11995 {
11996   branch_history_t *result = apr_palloc(result_pool, sizeof(*result));
11997
11998   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(oldest_rev));
11999   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
12000   SVN_ERR_ASSERT(oldest_rev >= 1);
12001   /* Allow a just-empty range (oldest = youngest + 1) but not an
12002    * arbitrary reverse range (such as oldest = youngest + 2). */
12003   SVN_ERR_ASSERT(oldest_rev <= youngest_rev + 1);
12004
12005   if (oldest_rev <= youngest_rev)
12006     {
12007       SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
12008                 &result->history, branch_history->history,
12009                 youngest_rev, oldest_rev - 1, TRUE /* include_range */,
12010                 result_pool, scratch_pool));
12011       result->history = svn_mergeinfo_dup(result->history, result_pool);
12012     }
12013   else
12014     {
12015       result->history = apr_hash_make(result_pool);
12016     }
12017   result->has_r0_history = FALSE;
12018
12019   /* ### TODO: Set RESULT->tip to the tip of the intersection. */
12020   result->tip = svn_client__pathrev_dup(branch_history->tip, result_pool);
12021
12022   *intersection_p = result;
12023   return SVN_NO_ERROR;
12024 }
12025
12026 /* Set *OLDEST_P and *YOUNGEST_P to the oldest and youngest locations
12027  * (inclusive) along BRANCH.  OLDEST_P and/or YOUNGEST_P may be NULL if not
12028  * wanted.
12029  */
12030 static svn_error_t *
12031 branch_history_get_endpoints(svn_client__pathrev_t **oldest_p,
12032                              svn_client__pathrev_t **youngest_p,
12033                              const branch_history_t *branch,
12034                              apr_pool_t *result_pool,
12035                              apr_pool_t *scratch_pool)
12036 {
12037   svn_revnum_t youngest_rev, oldest_rev;
12038
12039   SVN_ERR(svn_mergeinfo__get_range_endpoints(
12040             &youngest_rev, &oldest_rev,
12041             branch->history, scratch_pool));
12042   if (oldest_p)
12043     *oldest_p = location_on_branch_at_rev(
12044                   branch, oldest_rev + 1, result_pool, scratch_pool);
12045   if (youngest_p)
12046     *youngest_p = location_on_branch_at_rev(
12047                     branch, youngest_rev, result_pool, scratch_pool);
12048   return SVN_NO_ERROR;
12049 }
12050
12051 /* Implements the svn_log_entry_receiver_t interface.
12052
12053   Set *BATON to LOG_ENTRY->revision and return SVN_ERR_CEASE_INVOCATION. */
12054 static svn_error_t *
12055 operative_rev_receiver(void *baton,
12056                        svn_log_entry_t *log_entry,
12057                        apr_pool_t *pool)
12058 {
12059   svn_revnum_t *operative_rev = baton;
12060
12061   *operative_rev = log_entry->revision;
12062
12063   /* We've found the youngest merged or oldest eligible revision, so
12064      we're done...
12065
12066      ...but wait, shouldn't we care if LOG_ENTRY->NON_INHERITABLE is
12067      true?  Because if it is, then LOG_ENTRY->REVISION is only
12068      partially merged/elgibile!  And our only caller,
12069      find_last_merged_location (via short_circuit_mergeinfo_log) is
12070      interested in *fully* merged revisions.  That's all true, but if
12071      find_last_merged_location() finds the youngest merged revision it
12072      will also check for the oldest eligible revision.  So in the case
12073      the youngest merged rev is non-inheritable, the *same* non-inheritable
12074      rev will be found as the oldest eligible rev -- and
12075      find_last_merged_location() handles that situation. */
12076   return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
12077 }
12078
12079 /* Wrapper around svn_client__mergeinfo_log. All arguments are as per
12080    that private API.  The discover_changed_paths, depth, and revprops args to
12081    svn_client__mergeinfo_log are always TRUE, svn_depth_infinity_t,
12082    and empty array respectively.
12083
12084    If RECEIVER raises a SVN_ERR_CEASE_INVOCATION error, but still sets
12085    *REVISION to a valid revnum, then clear the error.  Otherwise return
12086    any error. */
12087 static svn_error_t*
12088 short_circuit_mergeinfo_log(svn_mergeinfo_catalog_t *target_mergeinfo_cat,
12089                             svn_boolean_t finding_merged,
12090                             const char *target_path_or_url,
12091                             const svn_opt_revision_t *target_peg_revision,
12092                             const char *source_path_or_url,
12093                             const svn_opt_revision_t *source_peg_revision,
12094                             const svn_opt_revision_t *source_start_revision,
12095                             const svn_opt_revision_t *source_end_revision,
12096                             svn_log_entry_receiver_t receiver,
12097                             svn_revnum_t *revision,
12098                             svn_client_ctx_t *ctx,
12099                             svn_ra_session_t *ra_session,
12100                             apr_pool_t *result_pool,
12101                             apr_pool_t *scratch_pool)
12102 {
12103   apr_array_header_t *revprops;
12104   svn_error_t *err;
12105   const char *session_url;
12106
12107   SVN_ERR(svn_ra_get_session_url(ra_session, &session_url, scratch_pool));
12108
12109   revprops = apr_array_make(scratch_pool, 0, sizeof(const char *));
12110   err = svn_client__mergeinfo_log(finding_merged,
12111                                   target_path_or_url,
12112                                   target_peg_revision,
12113                                   target_mergeinfo_cat,
12114                                   source_path_or_url,
12115                                   source_peg_revision,
12116                                   source_start_revision,
12117                                   source_end_revision,
12118                                   receiver, revision,
12119                                   TRUE, svn_depth_infinity,
12120                                   revprops, ctx, ra_session,
12121                                   result_pool, scratch_pool);
12122
12123   err = svn_error_compose_create(
12124                   err,
12125                   svn_ra_reparent(ra_session, session_url, scratch_pool));
12126
12127   if (err)
12128     {
12129       /* We expect RECEIVER to short-circuit the (potentially expensive) log
12130          by raising an SVN_ERR_CEASE_INVOCATION -- see operative_rev_receiver.
12131          So we can ignore that error, but only as long as we actually found a
12132          valid revision. */
12133       if (SVN_IS_VALID_REVNUM(*revision)
12134           && err->apr_err == SVN_ERR_CEASE_INVOCATION)
12135         {
12136           svn_error_clear(err);
12137           err = NULL;
12138         }
12139       else
12140         {
12141           return svn_error_trace(err);
12142         }
12143     }
12144   return SVN_NO_ERROR;
12145 }
12146
12147 /* Set *BASE_P to the last location on SOURCE_BRANCH such that all changes
12148  * on SOURCE_BRANCH after YCA up to and including *BASE_P have already
12149  * been fully merged into TARGET.
12150  *
12151  *               *BASE_P       TIP
12152  *          o-------o-----------o--- SOURCE_BRANCH
12153  *         /         \
12154  *   -----o     prev. \
12155  *     YCA \    merges \
12156  *          o-----------o----------- TARGET branch
12157  *
12158  * In terms of mergeinfo:
12159  *
12160  *     Source     a--...                     o=change, -=no-op revision
12161  *       branch  /   \
12162  *     YCA -->  o     a---o---o---o---o---   d=delete, a=add-as-a-copy
12163  *
12164  *     Eligible -.eee.eeeeeeeeeeeeeeeeeeee   .=not a source branch location
12165  *
12166  *     Tgt-mi   -.mmm.mm-mm-------m-------   m=merged to root of TARGET or
12167  *                                           subtree of TARGET with no
12168  *                                           operative changes outside of that
12169  *                                           subtree, -=not merged
12170  *
12171  *     Eligible -.---.--e--eeeeeee-eeeeeee
12172  *
12173  *     Next     --------^-----------------   BASE is just before here.
12174  *
12175  *             /         \
12176  *       -----o     prev. \
12177  *         YCA \    merges \
12178  *              o-----------o-------------
12179  *
12180  * If no revisions from SOURCE_BRANCH have been completely merged to TARGET,
12181  * then set *BASE_P to the YCA.
12182  */
12183 static svn_error_t *
12184 find_last_merged_location(svn_client__pathrev_t **base_p,
12185                           svn_client__pathrev_t *yca,
12186                           const branch_history_t *source_branch,
12187                           svn_client__pathrev_t *target,
12188                           svn_client_ctx_t *ctx,
12189                           svn_ra_session_t *ra_session,
12190                           apr_pool_t *result_pool,
12191                           apr_pool_t *scratch_pool)
12192 {
12193   svn_opt_revision_t source_peg_rev, source_start_rev, source_end_rev,
12194     target_opt_rev;
12195   svn_revnum_t youngest_merged_rev = SVN_INVALID_REVNUM;
12196   svn_mergeinfo_catalog_t target_mergeinfo_cat = NULL;
12197
12198   source_peg_rev.kind = svn_opt_revision_number;
12199   source_peg_rev.value.number = source_branch->tip->rev;
12200   source_start_rev.kind = svn_opt_revision_number;
12201   source_start_rev.value.number = yca->rev;
12202   source_end_rev.kind = svn_opt_revision_number;
12203   source_end_rev.value.number = source_branch->tip->rev;
12204   target_opt_rev.kind = svn_opt_revision_number;
12205   target_opt_rev.value.number = target->rev;
12206
12207   /* Find the youngest revision fully merged from SOURCE_BRANCH to TARGET,
12208      if such a revision exists. */
12209   SVN_ERR(short_circuit_mergeinfo_log(&target_mergeinfo_cat,
12210                                       TRUE, /* Find merged */
12211                                       target->url, &target_opt_rev,
12212                                       source_branch->tip->url,
12213                                       &source_peg_rev,
12214                                       &source_end_rev, &source_start_rev,
12215                                       operative_rev_receiver,
12216                                       &youngest_merged_rev,
12217                                       ctx, ra_session,
12218                                       result_pool, scratch_pool));
12219
12220   if (!SVN_IS_VALID_REVNUM(youngest_merged_rev))
12221     {
12222       /* No revisions have been completely merged from SOURCE_BRANCH to
12223          TARGET so the base for the next merge is the YCA. */
12224       *base_p = yca;
12225     }
12226   else
12227     {
12228       /* One or more revisions have already been completely merged from
12229          SOURCE_BRANCH to TARGET, now find the oldest revision, older
12230          than the youngest merged revision, which is still eligible to
12231          be merged, if such exists. */
12232       branch_history_t *contiguous_source;
12233       svn_revnum_t base_rev;
12234       svn_revnum_t oldest_eligible_rev = SVN_INVALID_REVNUM;
12235
12236       /* If the only revisions eligible are younger than the youngest merged
12237          revision we can simply assume that the youngest eligible revision
12238          is the youngest merged revision.  Obviously this may not be true!
12239          The revisions between the youngest merged revision and the tip of
12240          the branch may have several inoperative revisions -- they may *all*
12241          be inoperative revisions!  But for the purpose of this function
12242          (i.e. finding the youngest revision after the YCA where all revs have
12243          been merged) that doesn't matter. */
12244       source_end_rev.value.number = youngest_merged_rev;
12245       SVN_ERR(short_circuit_mergeinfo_log(&target_mergeinfo_cat,
12246                                           FALSE, /* Find eligible */
12247                                           target->url, &target_opt_rev,
12248                                           source_branch->tip->url,
12249                                           &source_peg_rev,
12250                                           &source_start_rev, &source_end_rev,
12251                                           operative_rev_receiver,
12252                                           &oldest_eligible_rev,
12253                                           ctx, ra_session,
12254                                           scratch_pool, scratch_pool));
12255
12256       /* If there are revisions eligible for merging, use the oldest one
12257          to calculate the base.  Otherwise there are no operative revisions
12258          to merge and we can simple set the base to the youngest revision
12259          already merged. */
12260       if (SVN_IS_VALID_REVNUM(oldest_eligible_rev))
12261         base_rev = oldest_eligible_rev - 1;
12262       else
12263         base_rev = youngest_merged_rev;
12264
12265       /* Find the branch location just before the oldest eligible rev.
12266          (We can't just use the base revs calculated above because the branch
12267          might have a gap there.) */
12268       SVN_ERR(branch_history_intersect_range(&contiguous_source,
12269                                              source_branch, yca->rev,
12270                                              base_rev,
12271                                              scratch_pool, scratch_pool));
12272       SVN_ERR(branch_history_get_endpoints(NULL, base_p, contiguous_source,
12273                                            result_pool, scratch_pool));
12274     }
12275
12276   return SVN_NO_ERROR;
12277 }
12278
12279 /* Find a merge base location on the target branch, like in a sync
12280  * merge.
12281  *
12282  *                BASE          S_T->source
12283  *          o-------o-----------o---
12284  *         /         \           \
12285  *   -----o     prev. \           \  this
12286  *     YCA \    merge  \           \ merge
12287  *          o-----------o-----------o
12288  *                                  S_T->target
12289  *
12290  * Set *BASE_P to BASE, the youngest location in the history of S_T->source
12291  * (at or after the YCA) at which all revisions up to BASE are effectively
12292  * merged into S_T->target.
12293  *
12294  * If no locations on the history of S_T->source are effectively merged to
12295  * S_T->target, set *BASE_P to the YCA.
12296  */
12297 static svn_error_t *
12298 find_base_on_source(svn_client__pathrev_t **base_p,
12299                     source_and_target_t *s_t,
12300                     svn_client_ctx_t *ctx,
12301                     apr_pool_t *result_pool,
12302                     apr_pool_t *scratch_pool)
12303 {
12304   SVN_ERR(find_last_merged_location(base_p,
12305                                     s_t->yca,
12306                                     &s_t->source_branch,
12307                                     s_t->target_branch.tip,
12308                                     ctx,
12309                                     s_t->source_ra_session,
12310                                     result_pool, scratch_pool));
12311   return SVN_NO_ERROR;
12312 }
12313
12314 /* Find a merge base location on the target branch, like in a reintegrate
12315  * merge.
12316  *
12317  *                              S_T->source
12318  *          o-----------o-------o---
12319  *         /    prev.  /         \
12320  *   -----o     merge /           \  this
12321  *     YCA \         /             \ merge
12322  *          o-------o---------------o
12323  *                BASE              S_T->target
12324  *
12325  * Set *BASE_P to BASE, the youngest location in the history of S_T->target
12326  * (at or after the YCA) at which all revisions up to BASE are effectively
12327  * merged into S_T->source.
12328  *
12329  * If no locations on the history of S_T->target are effectively merged to
12330  * S_T->source, set *BASE_P to the YCA.
12331  */
12332 static svn_error_t *
12333 find_base_on_target(svn_client__pathrev_t **base_p,
12334                     source_and_target_t *s_t,
12335                     svn_client_ctx_t *ctx,
12336                     apr_pool_t *result_pool,
12337                     apr_pool_t *scratch_pool)
12338 {
12339   SVN_ERR(find_last_merged_location(base_p,
12340                                     s_t->yca,
12341                                     &s_t->target_branch,
12342                                     s_t->source,
12343                                     ctx,
12344                                     s_t->target_ra_session,
12345                                     result_pool, scratch_pool));
12346
12347   return SVN_NO_ERROR;
12348 }
12349
12350 /* The body of client_find_automatic_merge(), which see.
12351  */
12352 static svn_error_t *
12353 find_automatic_merge(svn_client__pathrev_t **base_p,
12354                      svn_boolean_t *is_reintegrate_like,
12355                      source_and_target_t *s_t,
12356                      svn_client_ctx_t *ctx,
12357                      apr_pool_t *result_pool,
12358                      apr_pool_t *scratch_pool)
12359 {
12360   svn_client__pathrev_t *base_on_source, *base_on_target;
12361
12362   /* Get the location-history of each branch. */
12363   s_t->source_branch.tip = s_t->source;
12364   SVN_ERR(svn_client__get_history_as_mergeinfo(
12365             &s_t->source_branch.history, &s_t->source_branch.has_r0_history,
12366             s_t->source, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
12367             s_t->source_ra_session, ctx, scratch_pool));
12368   s_t->target_branch.tip = &s_t->target->loc;
12369   SVN_ERR(svn_client__get_history_as_mergeinfo(
12370             &s_t->target_branch.history, &s_t->target_branch.has_r0_history,
12371             &s_t->target->loc, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
12372             s_t->target_ra_session, ctx, scratch_pool));
12373
12374   SVN_ERR(svn_client__calc_youngest_common_ancestor(
12375             &s_t->yca, s_t->source, s_t->source_branch.history,
12376             s_t->source_branch.has_r0_history,
12377             &s_t->target->loc, s_t->target_branch.history,
12378             s_t->target_branch.has_r0_history,
12379             result_pool, scratch_pool));
12380
12381   if (! s_t->yca)
12382     return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
12383                              _("'%s@%ld' must be ancestrally related to "
12384                                "'%s@%ld'"),
12385                              s_t->source->url, s_t->source->rev,
12386                              s_t->target->loc.url, s_t->target->loc.rev);
12387
12388   /* Find the latest revision of A synced to B and the latest
12389    * revision of B synced to A.
12390    *
12391    *   base_on_source = youngest_complete_synced_point(source, target)
12392    *   base_on_target = youngest_complete_synced_point(target, source)
12393    */
12394   SVN_ERR(find_base_on_source(&base_on_source, s_t,
12395                               ctx, scratch_pool, scratch_pool));
12396   SVN_ERR(find_base_on_target(&base_on_target, s_t,
12397                               ctx, scratch_pool, scratch_pool));
12398
12399   /* Choose a base. */
12400   if (base_on_source->rev >= base_on_target->rev)
12401     {
12402       *base_p = base_on_source;
12403       *is_reintegrate_like = FALSE;
12404     }
12405   else
12406     {
12407       *base_p = base_on_target;
12408       *is_reintegrate_like = TRUE;
12409     }
12410
12411   return SVN_NO_ERROR;
12412 }
12413
12414 /** Find out what kind of automatic merge would be needed, when the target
12415  * is only known as a repository location rather than a WC.
12416  *
12417  * Like find_automatic_merge() except that the target is
12418  * specified by @a target_path_or_url at @a target_revision, which must
12419  * refer to a repository location, instead of by a WC path argument.
12420  */
12421 static svn_error_t *
12422 find_automatic_merge_no_wc(automatic_merge_t **merge_p,
12423                            const char *source_path_or_url,
12424                            const svn_opt_revision_t *source_revision,
12425                            const char *target_path_or_url,
12426                            const svn_opt_revision_t *target_revision,
12427                            svn_client_ctx_t *ctx,
12428                            apr_pool_t *result_pool,
12429                            apr_pool_t *scratch_pool)
12430 {
12431   source_and_target_t *s_t = apr_palloc(scratch_pool, sizeof(*s_t));
12432   svn_client__pathrev_t *target_loc;
12433   automatic_merge_t *merge = apr_palloc(result_pool, sizeof(*merge));
12434
12435   /* Source */
12436   SVN_ERR(svn_client__ra_session_from_path2(
12437             &s_t->source_ra_session, &s_t->source,
12438             source_path_or_url, NULL, source_revision, source_revision,
12439             ctx, result_pool));
12440
12441   /* Target */
12442   SVN_ERR(svn_client__ra_session_from_path2(
12443             &s_t->target_ra_session, &target_loc,
12444             target_path_or_url, NULL, target_revision, target_revision,
12445             ctx, result_pool));
12446   s_t->target = apr_palloc(scratch_pool, sizeof(*s_t->target));
12447   s_t->target->abspath = NULL;  /* indicate the target is not a WC */
12448   s_t->target->loc = *target_loc;
12449
12450   SVN_ERR(find_automatic_merge(&merge->base, &merge->is_reintegrate_like, s_t,
12451                                ctx, result_pool, scratch_pool));
12452
12453   merge->right = s_t->source;
12454   merge->target = &s_t->target->loc;
12455   merge->yca = s_t->yca;
12456   *merge_p = merge;
12457
12458   return SVN_NO_ERROR;
12459 }
12460
12461 /* Find the information needed to merge all unmerged changes from a source
12462  * branch into a target branch.
12463  *
12464  * Set @a *merge_p to the information needed to merge all unmerged changes
12465  * (up to @a source_revision) from the source branch @a source_path_or_url
12466  * at @a source_revision into the target WC at @a target_abspath.
12467  *
12468  * The flags @a allow_mixed_rev, @a allow_local_mods and
12469  * @a allow_switched_subtrees enable merging into a WC that is in any or all
12470  * of the states described by their names, but only if this function decides
12471  * that the merge will be in the same direction as the last automatic merge.
12472  * If, on the other hand, the last automatic merge was in the opposite
12473  * direction, then such states of the WC are not allowed regardless
12474  * of these flags.  This function merely records these flags in the
12475  * @a *merge_p structure; do_automatic_merge_locked() checks the WC
12476  * state for compliance.
12477  *
12478  * Allocate the @a *merge_p structure in @a result_pool.
12479  */
12480 static svn_error_t *
12481 client_find_automatic_merge(automatic_merge_t **merge_p,
12482                             const char *source_path_or_url,
12483                             const svn_opt_revision_t *source_revision,
12484                             const char *target_abspath,
12485                             svn_boolean_t allow_mixed_rev,
12486                             svn_boolean_t allow_local_mods,
12487                             svn_boolean_t allow_switched_subtrees,
12488                             svn_client_ctx_t *ctx,
12489                             apr_pool_t *result_pool,
12490                             apr_pool_t *scratch_pool)
12491 {
12492   source_and_target_t *s_t = apr_palloc(result_pool, sizeof(*s_t));
12493   automatic_merge_t *merge = apr_palloc(result_pool, sizeof(*merge));
12494
12495   /* "Open" the target WC.  Check the target WC for mixed-rev, local mods and
12496    * switched subtrees yet to faster exit and notify user before contacting
12497    * with server.  After we find out what kind of merge is required, then if a
12498    * reintegrate-like merge is required we'll do the stricter checks, in
12499    * do_automatic_merge_locked(). */
12500   SVN_ERR(open_target_wc(&s_t->target, target_abspath,
12501                          allow_mixed_rev,
12502                          allow_local_mods,
12503                          allow_switched_subtrees,
12504                          ctx, result_pool, scratch_pool));
12505
12506   /* Open RA sessions to the source and target trees. */
12507   SVN_ERR(svn_client_open_ra_session2(&s_t->target_ra_session,
12508                                       s_t->target->loc.url,
12509                                       s_t->target->abspath,
12510                                       ctx, result_pool, scratch_pool));
12511   /* ### check for null URL (i.e. added path) here, like in reintegrate? */
12512   SVN_ERR(svn_client__ra_session_from_path2(
12513             &s_t->source_ra_session, &s_t->source,
12514             source_path_or_url, NULL, source_revision, source_revision,
12515             ctx, result_pool));
12516
12517   /* Check source is in same repos as target. */
12518   SVN_ERR(check_same_repos(s_t->source, source_path_or_url,
12519                            &s_t->target->loc, target_abspath,
12520                            TRUE /* strict_urls */, scratch_pool));
12521
12522   SVN_ERR(find_automatic_merge(&merge->base, &merge->is_reintegrate_like, s_t,
12523                                ctx, result_pool, scratch_pool));
12524   merge->yca = s_t->yca;
12525   merge->right = s_t->source;
12526   merge->allow_mixed_rev = allow_mixed_rev;
12527   merge->allow_local_mods = allow_local_mods;
12528   merge->allow_switched_subtrees = allow_switched_subtrees;
12529
12530   *merge_p = merge;
12531
12532   /* TODO: Close the source and target sessions here? */
12533
12534   return SVN_NO_ERROR;
12535 }
12536
12537 /* Perform an automatic merge, given the information in MERGE which
12538  * must have come from calling client_find_automatic_merge().
12539  *
12540  * Four locations are inputs: YCA, BASE, RIGHT, TARGET, as shown
12541  * depending on whether the base is on the source branch or the target
12542  * branch of this merge.
12543  *
12544  *                            RIGHT     (is_reintegrate_like)
12545  *          o-----------o-------o---
12546  *         /    prev.  /         \
12547  *   -----o     merge /           \  this
12548  *     YCA \         /             \ merge
12549  *          o-------o---------------o
12550  *                BASE            TARGET
12551  *
12552  * or
12553  *
12554  *                BASE        RIGHT      (! is_reintegrate_like)
12555  *          o-------o-----------o---
12556  *         /         \           \
12557  *   -----o     prev. \           \  this
12558  *     YCA \    merge  \           \ merge
12559  *          o-----------o-----------o
12560  *                                TARGET
12561  *
12562  * ### TODO: The reintegrate-like code path does not yet
12563  * eliminate already-cherry-picked revisions from the source.
12564  */
12565 static svn_error_t *
12566 do_automatic_merge_locked(conflict_report_t **conflict_report,
12567                           const automatic_merge_t *merge,
12568                           const char *target_abspath,
12569                           svn_depth_t depth,
12570                           svn_boolean_t diff_ignore_ancestry,
12571                           svn_boolean_t force_delete,
12572                           svn_boolean_t record_only,
12573                           svn_boolean_t dry_run,
12574                           const apr_array_header_t *merge_options,
12575                           svn_client_ctx_t *ctx,
12576                           apr_pool_t *result_pool,
12577                           apr_pool_t *scratch_pool)
12578 {
12579   merge_target_t *target;
12580   svn_boolean_t reintegrate_like = merge->is_reintegrate_like;
12581   svn_boolean_t use_sleep = FALSE;
12582   svn_error_t *err;
12583
12584   SVN_ERR(open_target_wc(&target, target_abspath,
12585                          merge->allow_mixed_rev && ! reintegrate_like,
12586                          merge->allow_local_mods && ! reintegrate_like,
12587                          merge->allow_switched_subtrees && ! reintegrate_like,
12588                          ctx, scratch_pool, scratch_pool));
12589
12590   if (reintegrate_like)
12591     {
12592       merge_source_t source;
12593       svn_ra_session_t *base_ra_session = NULL;
12594       svn_ra_session_t *right_ra_session = NULL;
12595       svn_ra_session_t *target_ra_session = NULL;
12596
12597       if (record_only)
12598         return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
12599                                 _("The required merge is reintegrate-like, "
12600                                   "and the record-only option "
12601                                   "cannot be used with this kind of merge"));
12602
12603       if (depth != svn_depth_unknown)
12604         return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
12605                                 _("The required merge is reintegrate-like, "
12606                                   "and the depth option "
12607                                   "cannot be used with this kind of merge"));
12608
12609       if (force_delete)
12610         return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
12611                                 _("The required merge is reintegrate-like, "
12612                                   "and the force_delete option "
12613                                   "cannot be used with this kind of merge"));
12614
12615       SVN_ERR(ensure_ra_session_url(&base_ra_session, merge->base->url,
12616                                     target->abspath, ctx, scratch_pool));
12617       SVN_ERR(ensure_ra_session_url(&right_ra_session, merge->right->url,
12618                                     target->abspath, ctx, scratch_pool));
12619       SVN_ERR(ensure_ra_session_url(&target_ra_session, target->loc.url,
12620                                     target->abspath, ctx, scratch_pool));
12621
12622       /* Check for and reject any abnormalities -- such as revisions that
12623        * have not yet been merged in the opposite direction -- that a
12624        * 'reintegrate' merge would have rejected. */
12625       {
12626         merge_source_t *source2;
12627
12628         SVN_ERR(find_reintegrate_merge(&source2, NULL,
12629                                        right_ra_session, merge->right,
12630                                        target_ra_session, target,
12631                                        ctx, scratch_pool, scratch_pool));
12632       }
12633
12634       source.loc1 = merge->base;
12635       source.loc2 = merge->right;
12636       source.ancestral = ! merge->is_reintegrate_like;
12637
12638       err = merge_cousins_and_supplement_mergeinfo(conflict_report,
12639                                                    &use_sleep,
12640                                                    target,
12641                                                    base_ra_session,
12642                                                    right_ra_session,
12643                                                    &source, merge->yca,
12644                                                    TRUE /* same_repos */,
12645                                                    depth,
12646                                                    FALSE /*diff_ignore_ancestry*/,
12647                                                    force_delete, record_only,
12648                                                    dry_run,
12649                                                    merge_options,
12650                                                    ctx,
12651                                                    result_pool, scratch_pool);
12652     }
12653   else /* ! merge->is_reintegrate_like */
12654     {
12655       /* Ignoring the base that we found, we pass the YCA instead and let
12656          do_merge() work out which subtrees need which revision ranges to
12657          be merged.  This enables do_merge() to fill in revision-range
12658          gaps that are older than the base that we calculated (which is
12659          for the root path of the merge).
12660
12661          An improvement would be to change find_automatic_merge() to
12662          find the base for each sutree, and then here use the oldest base
12663          among all subtrees. */
12664       apr_array_header_t *merge_sources;
12665       svn_ra_session_t *ra_session = NULL;
12666
12667       /* Normalize our merge sources, do_merge() requires this.  See the
12668          'MERGEINFO MERGE SOURCE NORMALIZATION' global comment. */
12669       SVN_ERR(ensure_ra_session_url(&ra_session, merge->right->url,
12670                                     target->abspath, ctx, scratch_pool));
12671       SVN_ERR(normalize_merge_sources_internal(
12672         &merge_sources, merge->right,
12673         svn_rangelist__initialize(merge->yca->rev, merge->right->rev, TRUE,
12674                                   scratch_pool),
12675         ra_session, ctx, scratch_pool, scratch_pool));
12676
12677       err = do_merge(NULL, NULL, conflict_report, &use_sleep,
12678                      merge_sources, target, ra_session,
12679                      TRUE /*related*/, TRUE /*same_repos*/,
12680                      FALSE /*ignore_mergeinfo*/, diff_ignore_ancestry,
12681                      force_delete, dry_run,
12682                      record_only, NULL, FALSE, FALSE, depth, merge_options,
12683                      ctx, result_pool, scratch_pool);
12684     }
12685
12686   if (use_sleep)
12687     svn_io_sleep_for_timestamps(target_abspath, scratch_pool);
12688
12689   SVN_ERR(err);
12690
12691   return SVN_NO_ERROR;
12692 }
12693
12694 svn_error_t *
12695 svn_client_get_merging_summary(svn_boolean_t *needs_reintegration,
12696                                const char **yca_url, svn_revnum_t *yca_rev,
12697                                const char **base_url, svn_revnum_t *base_rev,
12698                                const char **right_url, svn_revnum_t *right_rev,
12699                                const char **target_url, svn_revnum_t *target_rev,
12700                                const char **repos_root_url,
12701                                const char *source_path_or_url,
12702                                const svn_opt_revision_t *source_revision,
12703                                const char *target_path_or_url,
12704                                const svn_opt_revision_t *target_revision,
12705                                svn_client_ctx_t *ctx,
12706                                apr_pool_t *result_pool,
12707                                apr_pool_t *scratch_pool)
12708 {
12709   svn_boolean_t target_is_wc;
12710   automatic_merge_t *merge;
12711
12712   target_is_wc = (! svn_path_is_url(target_path_or_url))
12713                  && (target_revision->kind == svn_opt_revision_unspecified
12714                      || target_revision->kind == svn_opt_revision_working);
12715   if (target_is_wc)
12716     SVN_ERR(client_find_automatic_merge(
12717               &merge,
12718               source_path_or_url, source_revision,
12719               target_path_or_url,
12720               TRUE, TRUE, TRUE,  /* allow_* */
12721               ctx, scratch_pool, scratch_pool));
12722   else
12723     SVN_ERR(find_automatic_merge_no_wc(
12724               &merge,
12725               source_path_or_url, source_revision,
12726               target_path_or_url, target_revision,
12727               ctx, scratch_pool, scratch_pool));
12728
12729   if (needs_reintegration)
12730     *needs_reintegration = merge->is_reintegrate_like;
12731   if (yca_url)
12732     *yca_url = apr_pstrdup(result_pool, merge->yca->url);
12733   if (yca_rev)
12734     *yca_rev = merge->yca->rev;
12735   if (base_url)
12736     *base_url = apr_pstrdup(result_pool, merge->base->url);
12737   if (base_rev)
12738     *base_rev = merge->base->rev;
12739   if (right_url)
12740     *right_url = apr_pstrdup(result_pool, merge->right->url);
12741   if (right_rev)
12742     *right_rev = merge->right->rev;
12743   if (target_url)
12744     *target_url = apr_pstrdup(result_pool, merge->target->url);
12745   if (target_rev)
12746     *target_rev = merge->target->rev;
12747   if (repos_root_url)
12748     *repos_root_url = apr_pstrdup(result_pool, merge->yca->repos_root_url);
12749
12750   return SVN_NO_ERROR;
12751 }