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