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