]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/subversion/subversion/libsvn_client/merge.c
MFC r275385 (by bapt):
[FreeBSD/stable/10.git] / contrib / subversion / subversion / libsvn_client / merge.c
1 /*
2  * merge.c: merging
3  *
4  * ====================================================================
5  *    Licensed to the Apache Software Foundation (ASF) under one
6  *    or more contributor license agreements.  See the NOTICE file
7  *    distributed with this work for additional information
8  *    regarding copyright ownership.  The ASF licenses this file
9  *    to you under the Apache License, Version 2.0 (the
10  *    "License"); you may not use this file except in compliance
11  *    with the License.  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  *    Unless required by applicable law or agreed to in writing,
16  *    software distributed under the License is distributed on an
17  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18  *    KIND, either express or implied.  See the License for the
19  *    specific language governing permissions and limitations
20  *    under the License.
21  * ====================================================================
22  */
23
24 /* ==================================================================== */
25
26
27 \f
28 /*** Includes ***/
29
30 #include <assert.h>
31 #include <apr_strings.h>
32 #include <apr_tables.h>
33 #include <apr_hash.h>
34 #include "svn_types.h"
35 #include "svn_hash.h"
36 #include "svn_wc.h"
37 #include "svn_delta.h"
38 #include "svn_diff.h"
39 #include "svn_mergeinfo.h"
40 #include "svn_client.h"
41 #include "svn_string.h"
42 #include "svn_error.h"
43 #include "svn_dirent_uri.h"
44 #include "svn_path.h"
45 #include "svn_io.h"
46 #include "svn_utf.h"
47 #include "svn_pools.h"
48 #include "svn_config.h"
49 #include "svn_props.h"
50 #include "svn_time.h"
51 #include "svn_sorts.h"
52 #include "svn_subst.h"
53 #include "svn_ra.h"
54 #include "client.h"
55 #include "mergeinfo.h"
56
57 #include "private/svn_fspath.h"
58 #include "private/svn_mergeinfo_private.h"
59 #include "private/svn_client_private.h"
60 #include "private/svn_sorts_private.h"
61 #include "private/svn_subr_private.h"
62 #include "private/svn_wc_private.h"
63
64 #include "svn_private_config.h"
65
66
67 /*-----------------------------------------------------------------------*/
68 \f
69 /* MERGEINFO MERGE SOURCE NORMALIZATION
70  *
71  * Nearly any helper function herein that accepts two URL/revision
72  * pairs (or equivalent struct merge_source_t) expects one of two things
73  * to be true:
74  *
75  *    1.  that mergeinfo is not being recorded at all for this
76  *        operation, or
77  *
78  *    2.  that the pairs represent two locations along a single line
79  *        of version history such that there are no copies in the
80  *        history of the object between the locations when treating
81  *        the oldest of the two locations as non-inclusive.  In other
82  *        words, if there is a copy at all between them, there is only
83  *        one copy and its source was the oldest of the two locations.
84  *
85  * We use svn_ra_get_location_segments() to split a given range of
86  * revisions across an object's history into several which obey these
87  * rules.  For example, an extract from the log of Subversion's own
88  * /subversion/tags/1.4.5 directory shows the following copies between
89  * r859500 and r866500 (omitting the '/subversion' prefix for clarity):
90  *
91  *    r859598:
92  *      A /branches/1.4.x  (from /trunk:859597)
93  *
94  *    r865417:
95  *      A /tags/1.4.4      (from /branches/1.4.x:865262)
96  *    # Notice that this copy leaves a gap between 865262 and 865417.
97  *
98  *    r866420:
99  *      A /branches/1.4.5  (from /tags/1.4.4:866419)
100  *
101  *    r866425:
102  *      D /branches/1.4.5
103  *      A /tags/1.4.5      (from /branches/1.4.5:866424)
104  *
105  * In graphical form:
106  *
107  *                859500 859597 865262        866419 866424 866500
108  *                  .      .      .             .      .      .
109  *    trunk       ------------------------------------------------
110  *                         \      .             .      .
111  *    branches/1.4.x        A-------------------------------------
112  *                          .     \______       .      .
113  *                          .            \      .      .
114  *    tags/1.4.4            .             A-----------------------
115  *                          .             .     \      .
116  *    branches/1.4.5        .             .      A------D
117  *                          .             .      .     \.
118  *    tags/1.4.5            .             .      .      A---------
119  *                          .             .      .      .
120  *                       859598        865417 866420 866425
121  *
122  * A merge of the difference between r859500 and r866500 of this directory
123  * gets split into sequential merges of the following location pairs.
124  *
125  *                859500 859597 865262 865416 866419 866424 866500
126  *                  .      .      .      .      .      .      .
127  *    trunk         (======]      .      .      .      .      .
128  *                                .      .      .      .      .
129  *    trunk                (      .      .      .      .      .
130  *    branches/1.4.x        ======]      .      .      .      .
131  *                                       .      .      .      .
132  *    branches/1.4.x              (      .      .      .      .
133  *    tags/1.4.4                   =============]      .      .
134  *    implicit_src_gap            (======]      .      .      .
135  *                                              .      .      .
136  *    tags/1.4.4                                (      .      .
137  *    branches/1.4.5                             ======]      .
138  *                                                     .      .
139  *    branches/1.4.5                                   (      .
140  *    tags/1.4.5                                        ======]
141  *
142  * which are represented in merge_source_t as:
143  *
144  *    [/trunk:859500, /trunk:859597]
145  *    (recorded in svn:mergeinfo as /trunk:859501-859597)
146  *
147  *    [/trunk:859597, /branches/1.4.x:865262]
148  *    (recorded in svn:mergeinfo as /branches/1.4.x:859598-865262)
149  *
150  *    [/branches/1.4.x:865262, /tags/1.4.4@866419]
151  *    (recorded in svn:mergeinfo as /tags/1.4.4:865263-866419)
152  *    (and there is a gap, the revision range [865262, 865416])
153  *
154  *    [/tags/1.4.4@866419, /branches/1.4.5@866424]
155  *    (recorded in svn:mergeinfo as /branches/1.4.5:866420-866424)
156  *
157  *    [/branches/1.4.5@866424, /tags/1.4.5@866500]
158  *    (recorded in svn:mergeinfo as /tags/1.4.5:866425-866500)
159  *
160  * Our helper functions would then operate on one of these location
161  * pairs at a time.
162  */
163
164 /* WHICH SVN_CLIENT_MERGE* API DO I WANT?
165  *
166  * libsvn_client has three public merge APIs; they are all wrappers
167  * around the do_merge engine.  Which one to use depends on the number
168  * of URLs passed as arguments and whether or not specific merge
169  * ranges (-c/-r) are specified.
170  *
171  *                 1 URL                        2 URLs
172  * +----+--------------------------------+---------------------+
173  * | -c |       mergeinfo-driven         |                     |
174  * | or |        cherrypicking           |                     |
175  * | -r |    (svn_client_merge_peg)      |                     |
176  * |----+--------------------------------+                     |
177  * |    |       mergeinfo-driven         |     unsupported     |
178  * |    |  'cherry harvest', i.e. merge  |                     |
179  * |    |  all revisions from URL that   |                     |
180  * | no |  have not already been merged  |                     |
181  * | -c |    (svn_client_merge_peg)      |                     |
182  * | or +--------------------------------+---------------------+
183  * | -r |      mergeinfo-driven          |   mergeinfo-writing |
184  * |    |        whole-branch            |    diff-and-apply   |
185  * |    |       heuristic merge          |  (svn_client_merge) |
186  * |    | (svn_client_merge_reintegrate) |                     |
187  * +----+--------------------------------+---------------------+
188  *
189  *
190  */
191
192 /* THE CHILDREN_WITH_MERGEINFO ARRAY
193  *
194  * Many of the helper functions in this file pass around an
195  * apr_array_header_t *CHILDREN_WITH_MERGEINFO.  This is a depth first
196  * sorted array filled with svn_client__merge_path_t * describing the
197  * merge target and any of its subtrees which have explicit mergeinfo
198  * or otherwise need special attention during a merge.
199  *
200  * During mergeinfo unaware merges, CHILDREN_WITH_MERGEINFO contains
201  * contains only one element (added by do_mergeinfo_unaware_dir_merge)
202  * describing a contiguous range to be merged to the WC merge target.
203  *
204  * During mergeinfo aware merges CHILDREN_WITH_MERGEINFO is created
205  * by get_mergeinfo_paths() and outside of that function and its helpers
206  * should always meet the criteria dictated in get_mergeinfo_paths()'s doc
207  * string.  The elements of CHILDREN_WITH_MERGEINFO should never be NULL.
208  *
209  * For clarification on mergeinfo aware vs. mergeinfo unaware merges, see
210  * the doc string for HONOR_MERGEINFO().
211  */
212
213
214 /*-----------------------------------------------------------------------*/
215 \f
216 /*** Repos-Diff Editor Callbacks ***/
217
218 /* */
219 typedef struct merge_source_t
220 {
221   /* "left" side URL and revision (inclusive iff youngest) */
222   const svn_client__pathrev_t *loc1;
223
224   /* "right" side URL and revision (inclusive iff youngest) */
225   const svn_client__pathrev_t *loc2;
226
227   /* True iff LOC1 is an ancestor of LOC2 or vice-versa (history-wise). */
228   svn_boolean_t ancestral;
229 } merge_source_t;
230
231 /* Description of the merge target root node (a WC working node) */
232 typedef struct merge_target_t
233 {
234   /* Absolute path to the WC node */
235   const char *abspath;
236
237   /* The repository location of the base node of the target WC.  If the node
238    * is locally added, then URL & REV are NULL & SVN_INVALID_REVNUM.
239    * REPOS_ROOT_URL and REPOS_UUID are always valid. */
240   svn_client__pathrev_t loc;
241
242 } merge_target_t;
243
244 typedef struct merge_cmd_baton_t {
245   svn_boolean_t force_delete;         /* Delete a file/dir even if modified */
246   svn_boolean_t dry_run;
247   svn_boolean_t record_only;          /* Whether to merge only mergeinfo
248                                          differences. */
249   svn_boolean_t same_repos;           /* Whether the merge source repository
250                                          is the same repository as the
251                                          target.  Defaults to FALSE if DRY_RUN
252                                          is TRUE.*/
253   svn_boolean_t mergeinfo_capable;    /* Whether the merge source server
254                                          is capable of Merge Tracking. */
255   svn_boolean_t ignore_mergeinfo;     /* Don't honor mergeinfo; see
256                                          doc string of do_merge().  FALSE if
257                                          MERGE_SOURCE->ancestral is FALSE. */
258   svn_boolean_t diff_ignore_ancestry; /* Diff unrelated nodes as if related; see
259                                          doc string of do_merge().  FALSE if
260                                          MERGE_SOURCE->ancestral is FALSE. */
261   svn_boolean_t reintegrate_merge;    /* Whether this is a --reintegrate
262                                          merge or not. */
263   const merge_target_t *target;       /* Description of merge target node */
264
265   /* The left and right URLs and revs.  The value of this field changes to
266      reflect the merge_source_t *currently* being merged by do_merge(). */
267   merge_source_t merge_source;
268
269   /* Rangelist containing single range which describes the gap, if any,
270      in the natural history of the merge source currently being processed.
271      See http://subversion.tigris.org/issues/show_bug.cgi?id=3432.
272      Updated during each call to do_directory_merge().  May be NULL if there
273      is no gap. */
274   svn_rangelist_t *implicit_src_gap;
275
276   svn_client_ctx_t *ctx;              /* Client context for callbacks, etc. */
277
278   /* The list of any paths which remained in conflict after a
279      resolution attempt was made.  We track this in-memory, rather
280      than just using WC entry state, since the latter doesn't help us
281      when in dry_run mode.
282      ### And because we only want to resolve conflicts that were
283          generated by this merge, not pre-existing ones? */
284   apr_hash_t *conflicted_paths;
285
286   /* A list of absolute paths which had no explicit mergeinfo prior to the
287      merge but got explicit mergeinfo added by the merge.  This is populated
288      by merge_change_props() and is allocated in POOL so it is subject to the
289      lifetime limitations of POOL.  Is NULL if no paths are found which
290      meet the criteria or DRY_RUN is true. */
291   apr_hash_t *paths_with_new_mergeinfo;
292
293   /* A list of absolute paths whose mergeinfo doesn't need updating after
294      the merge. This can be caused by the removal of mergeinfo by the merge
295      or by deleting the node itself.  This is populated by merge_change_props()
296      and the delete callbacks and is allocated in POOL so it is subject to the
297      lifetime limitations of POOL.  Is NULL if no paths are found which
298      meet the criteria or DRY_RUN is true. */
299   apr_hash_t *paths_with_deleted_mergeinfo;
300
301   /* The list of absolute skipped paths, which should be examined and
302      cleared after each invocation of the callback.  The paths
303      are absolute.  Is NULL if MERGE_B->MERGE_SOURCE->ancestral and
304      MERGE_B->REINTEGRATE_MERGE are both false. */
305   apr_hash_t *skipped_abspaths;
306
307   /* The list of absolute merged paths.  Unused if MERGE_B->MERGE_SOURCE->ancestral
308      and MERGE_B->REINTEGRATE_MERGE are both false. */
309   apr_hash_t *merged_abspaths;
310
311   /* A hash of (const char *) absolute WC paths mapped to the same which
312      represent the roots of subtrees added by the merge. */
313   apr_hash_t *added_abspaths;
314
315   /* A list of tree conflict victim absolute paths which may be NULL. */
316   apr_hash_t *tree_conflicted_abspaths;
317
318   /* The diff3_cmd in ctx->config, if any, else null.  We could just
319      extract this as needed, but since more than one caller uses it,
320      we just set it up when this baton is created. */
321   const char *diff3_cmd;
322   const apr_array_header_t *merge_options;
323
324   /* Array of file extension patterns to preserve as extensions in
325      generated conflict files. */
326   const apr_array_header_t *ext_patterns;
327
328   /* RA sessions used throughout a merge operation.  Opened/re-parented
329      as needed.
330
331      NOTE: During the actual merge editor drive, RA_SESSION1 is used
332      for the primary editing and RA_SESSION2 for fetching additional
333      information -- as necessary -- from the repository.  So during
334      this phase of the merge, you *must not* reparent RA_SESSION1; use
335      (temporarily reparenting if you must) RA_SESSION2 instead.  */
336   svn_ra_session_t *ra_session1;
337   svn_ra_session_t *ra_session2;
338
339   /* During the merge, *USE_SLEEP is set to TRUE if a sleep will be required
340      afterwards to ensure timestamp integrity, or unchanged if not. */
341   svn_boolean_t *use_sleep;
342
343   /* Pool which has a lifetime limited to one iteration over a given
344      merge source, i.e. it is cleared on every call to do_directory_merge()
345      or do_file_merge() in do_merge(). */
346   apr_pool_t *pool;
347
348
349   /* State for notify_merge_begin() */
350   struct notify_begin_state_t
351   {
352     /* Cache of which abspath was last notified. */
353     const char *last_abspath;
354
355     /* Reference to the one-and-only CHILDREN_WITH_MERGEINFO (see global
356        comment) or a similar list for single-file-merges */
357     const apr_array_header_t *nodes_with_mergeinfo;
358   } notify_begin;
359
360 } merge_cmd_baton_t;
361
362
363 /* Return TRUE iff we should be taking account of mergeinfo in deciding what
364    changes to merge, for the merge described by MERGE_B.  Specifically, that
365    is if the merge source server is capable of merge tracking, the left-side
366    merge source is an ancestor of the right-side (or vice-versa), the merge
367    source is in the same repository as the merge target, and we are not
368    ignoring mergeinfo. */
369 #define HONOR_MERGEINFO(merge_b) ((merge_b)->mergeinfo_capable      \
370                                   && (merge_b)->merge_source.ancestral  \
371                                   && (merge_b)->same_repos          \
372                                   && (! (merge_b)->ignore_mergeinfo))
373
374
375 /* Return TRUE iff we should be recording mergeinfo for the merge described
376    by MERGE_B.  Specifically, that is if we are honoring mergeinfo and the
377    merge is not a dry run.  */
378 #define RECORD_MERGEINFO(merge_b) (HONOR_MERGEINFO(merge_b) \
379                                    && !(merge_b)->dry_run)
380
381
382 /*-----------------------------------------------------------------------*/
383 \f
384 /*** Utilities ***/
385
386 /* Return TRUE iff the session URL of RA_SESSION is equal to URL.  Useful in
387  * asserting preconditions. */
388 static svn_boolean_t
389 session_url_is(svn_ra_session_t *ra_session,
390                const char *url,
391                apr_pool_t *scratch_pool)
392 {
393   const char *session_url;
394   svn_error_t *err
395     = svn_ra_get_session_url(ra_session, &session_url, scratch_pool);
396
397   SVN_ERR_ASSERT_NO_RETURN(! err);
398   return strcmp(url, session_url) == 0;
399 }
400
401 /* Return a new merge_source_t structure, allocated in RESULT_POOL,
402  * initialized with deep copies of LOC1 and LOC2 and ANCESTRAL. */
403 static merge_source_t *
404 merge_source_create(const svn_client__pathrev_t *loc1,
405                     const svn_client__pathrev_t *loc2,
406                     svn_boolean_t ancestral,
407                     apr_pool_t *result_pool)
408 {
409   merge_source_t *s
410     = apr_palloc(result_pool, sizeof(*s));
411
412   s->loc1 = svn_client__pathrev_dup(loc1, result_pool);
413   s->loc2 = svn_client__pathrev_dup(loc2, result_pool);
414   s->ancestral = ancestral;
415   return s;
416 }
417
418 /* Return a deep copy of SOURCE, allocated in RESULT_POOL. */
419 static merge_source_t *
420 merge_source_dup(const merge_source_t *source,
421                  apr_pool_t *result_pool)
422 {
423   merge_source_t *s = apr_palloc(result_pool, sizeof(*s));
424
425   s->loc1 = svn_client__pathrev_dup(source->loc1, result_pool);
426   s->loc2 = svn_client__pathrev_dup(source->loc2, result_pool);
427   s->ancestral = source->ancestral;
428   return s;
429 }
430
431 /* Return SVN_ERR_UNSUPPORTED_FEATURE if URL is not inside the repository
432    of LOCAL_ABSPATH.  Use SCRATCH_POOL for temporary allocations. */
433 static svn_error_t *
434 check_repos_match(const merge_target_t *target,
435                   const char *local_abspath,
436                   const char *url,
437                   apr_pool_t *scratch_pool)
438 {
439   if (!svn_uri__is_ancestor(target->loc.repos_root_url, url))
440     return svn_error_createf(
441         SVN_ERR_UNSUPPORTED_FEATURE, NULL,
442          _("URL '%s' of '%s' is not in repository '%s'"),
443          url, svn_dirent_local_style(local_abspath, scratch_pool),
444          target->loc.repos_root_url);
445
446   return SVN_NO_ERROR;
447 }
448
449 /* Return TRUE iff the repository of LOCATION1 is the same as
450  * that of LOCATION2.  If STRICT_URLS is true, the URLs must
451  * match (and the UUIDs, just to be sure), otherwise just the UUIDs must
452  * match and the URLs can differ (a common case is http versus https). */
453 static svn_boolean_t
454 is_same_repos(const svn_client__pathrev_t *location1,
455               const svn_client__pathrev_t *location2,
456               svn_boolean_t strict_urls)
457 {
458   if (strict_urls)
459     return (strcmp(location1->repos_root_url, location2->repos_root_url) == 0
460             && strcmp(location1->repos_uuid, location2->repos_uuid) == 0);
461   else
462     return (strcmp(location1->repos_uuid, location2->repos_uuid) == 0);
463 }
464
465 /* If the repository identified of LOCATION1 is not the same as that
466  * of LOCATION2, throw a SVN_ERR_CLIENT_UNRELATED_RESOURCES
467  * error mentioning PATH1 and PATH2. For STRICT_URLS, see is_same_repos().
468  */
469 static svn_error_t *
470 check_same_repos(const svn_client__pathrev_t *location1,
471                  const char *path1,
472                  const svn_client__pathrev_t *location2,
473                  const char *path2,
474                  svn_boolean_t strict_urls,
475                  apr_pool_t *scratch_pool)
476 {
477   if (! is_same_repos(location1, location2, strict_urls))
478     return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
479                              _("'%s' must be from the same repository as "
480                                "'%s'"), path1, path2);
481   return SVN_NO_ERROR;
482 }
483
484 /* Store LOCAL_ABSPATH in PATH_HASH after duplicating it into the pool
485    containing PATH_HASH. */
486 static APR_INLINE void
487 store_path(apr_hash_t *path_hash, const char *local_abspath)
488 {
489   const char *dup_path = apr_pstrdup(apr_hash_pool_get(path_hash),
490                                      local_abspath);
491
492   svn_hash_sets(path_hash, dup_path, dup_path);
493 }
494
495 /* Store LOCAL_ABSPATH in *PATH_HASH_P after duplicating it into the pool
496    containing *PATH_HASH_P.  If *PATH_HASH_P is NULL, then first set
497    *PATH_HASH_P to a new hash allocated from POOL.  */
498 static APR_INLINE void
499 alloc_and_store_path(apr_hash_t **path_hash_p,
500                      const char *local_abspath,
501                      apr_pool_t *pool)
502 {
503   if (! *path_hash_p)
504     *path_hash_p = apr_hash_make(pool);
505   store_path(*path_hash_p, local_abspath);
506 }
507
508 /* Return whether any WC path was put in conflict by the merge
509    operation corresponding to MERGE_B. */
510 static APR_INLINE svn_boolean_t
511 is_path_conflicted_by_merge(merge_cmd_baton_t *merge_b)
512 {
513   return (merge_b->conflicted_paths &&
514           apr_hash_count(merge_b->conflicted_paths) > 0);
515 }
516
517 /* Return a state indicating whether the WC metadata matches the
518  * node kind on disk of the local path LOCAL_ABSPATH.
519  * Use MERGE_B to determine the dry-run details; particularly, if a dry run
520  * noted that it deleted this path, assume matching node kinds (as if both
521  * kinds were svn_node_none).
522  *
523  *   - Return svn_wc_notify_state_inapplicable if the node kind matches.
524  *   - Return 'obstructed' if there is a node on disk where none or a
525  *     different kind is expected, or if the disk node cannot be read.
526  *   - Return 'missing' if there is no node on disk but one is expected.
527  *     Also return 'missing' for server-excluded nodes (not here due to
528  *     authz or other reasons determined by the server).
529  *
530  * Optionally return a bit more info for interested users.
531  **/
532 static svn_error_t *
533 perform_obstruction_check(svn_wc_notify_state_t *obstruction_state,
534                           svn_boolean_t *deleted,
535                           svn_boolean_t *excluded,
536                           svn_node_kind_t *kind,
537                           svn_depth_t *parent_depth,
538                           const merge_cmd_baton_t *merge_b,
539                           const char *local_abspath,
540                           apr_pool_t *scratch_pool)
541 {
542   svn_wc_context_t *wc_ctx = merge_b->ctx->wc_ctx;
543   svn_node_kind_t wc_kind;
544   svn_boolean_t check_root;
545
546   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
547
548   *obstruction_state = svn_wc_notify_state_inapplicable;
549
550   if (deleted)
551     *deleted = FALSE;
552   if (kind)
553     *kind = svn_node_none;
554
555   if (kind == NULL)
556     kind = &wc_kind;
557
558   check_root = ! strcmp(local_abspath, merge_b->target->abspath);
559
560   SVN_ERR(svn_wc__check_for_obstructions(obstruction_state,
561                                          kind,
562                                          deleted,
563                                          excluded,
564                                          parent_depth,
565                                          wc_ctx, local_abspath,
566                                          check_root,
567                                          scratch_pool));
568   return SVN_NO_ERROR;
569 }
570
571 /* Create *LEFT and *RIGHT conflict versions for conflict victim
572  * at VICTIM_ABSPATH, with merge-left node kind MERGE_LEFT_NODE_KIND
573  * and merge-right node kind MERGE_RIGHT_NODE_KIND, using information
574  * obtained from MERGE_SOURCE and TARGET.
575  * Allocate returned conflict versions in RESULT_POOL. */
576 static svn_error_t *
577 make_conflict_versions(const svn_wc_conflict_version_t **left,
578                        const svn_wc_conflict_version_t **right,
579                        const char *victim_abspath,
580                        svn_node_kind_t merge_left_node_kind,
581                        svn_node_kind_t merge_right_node_kind,
582                        const merge_source_t *merge_source,
583                        const merge_target_t *target,
584                        apr_pool_t *result_pool,
585                        apr_pool_t *scratch_pool)
586 {
587   const char *child = svn_dirent_skip_ancestor(target->abspath,
588                                                victim_abspath);
589   const char *left_relpath, *right_relpath;
590
591   SVN_ERR_ASSERT(child != NULL);
592   left_relpath = svn_client__pathrev_relpath(merge_source->loc1,
593                                              scratch_pool);
594   right_relpath = svn_client__pathrev_relpath(merge_source->loc2,
595                                               scratch_pool);
596
597   *left = svn_wc_conflict_version_create2(
598             merge_source->loc1->repos_root_url,
599             merge_source->loc1->repos_uuid,
600             svn_relpath_join(left_relpath, child, scratch_pool),
601             merge_source->loc1->rev,
602             merge_left_node_kind, result_pool);
603
604   *right = svn_wc_conflict_version_create2(
605              merge_source->loc2->repos_root_url,
606              merge_source->loc2->repos_uuid,
607              svn_relpath_join(right_relpath, child, scratch_pool),
608              merge_source->loc2->rev,
609              merge_right_node_kind, result_pool);
610
611   return SVN_NO_ERROR;
612 }
613
614 /* Helper for filter_self_referential_mergeinfo()
615
616    *MERGEINFO is a non-empty, non-null collection of mergeinfo.
617
618    Remove all mergeinfo from *MERGEINFO that describes revision ranges
619    greater than REVISION.  Put a copy of any removed mergeinfo, allocated
620    in POOL, into *YOUNGER_MERGEINFO.
621
622    If no mergeinfo is removed from *MERGEINFO then *YOUNGER_MERGEINFO is set
623    to NULL.  If all mergeinfo is removed from *MERGEINFO then *MERGEINFO is
624    set to NULL.
625    */
626 static svn_error_t*
627 split_mergeinfo_on_revision(svn_mergeinfo_t *younger_mergeinfo,
628                             svn_mergeinfo_t *mergeinfo,
629                             svn_revnum_t revision,
630                             apr_pool_t *pool)
631 {
632   apr_hash_index_t *hi;
633   apr_pool_t *iterpool = svn_pool_create(pool);
634
635   *younger_mergeinfo = NULL;
636   for (hi = apr_hash_first(pool, *mergeinfo); hi; hi = apr_hash_next(hi))
637     {
638       int i;
639       const char *merge_source_path = apr_hash_this_key(hi);
640       svn_rangelist_t *rangelist = apr_hash_this_val(hi);
641
642       svn_pool_clear(iterpool);
643
644       for (i = 0; i < rangelist->nelts; i++)
645         {
646           svn_merge_range_t *range =
647             APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
648           if (range->end <= revision)
649             {
650               /* This entirely of this range is as old or older than
651                  REVISION, so leave it in *MERGEINFO. */
652               continue;
653             }
654           else
655             {
656               /* Since the rangelists in svn_mergeinfo_t's are sorted in
657                  increasing order we know that part or all of *this* range
658                  and *all* of the remaining ranges in *RANGELIST are younger
659                  than REVISION.  Remove the younger rangelists from
660                  *MERGEINFO and put them in *YOUNGER_MERGEINFO. */
661               int j;
662               svn_rangelist_t *younger_rangelist =
663                 apr_array_make(pool, 1, sizeof(svn_merge_range_t *));
664
665               for (j = i; j < rangelist->nelts; j++)
666                 {
667                   svn_merge_range_t *younger_range = svn_merge_range_dup(
668                     APR_ARRAY_IDX(rangelist, j, svn_merge_range_t *), pool);
669
670                   /* REVISION might intersect with the first range where
671                      range->end > REVISION.  If that is the case then split
672                      the current range into two, putting the younger half
673                      into *YOUNGER_MERGEINFO and leaving the older half in
674                      *MERGEINFO. */
675                   if (j == i && range->start + 1 <= revision)
676                     younger_range->start = range->end = revision;
677
678                   APR_ARRAY_PUSH(younger_rangelist, svn_merge_range_t *) =
679                     younger_range;
680                 }
681
682               /* So far we've only been manipulating rangelists, now we
683                  actually create *YOUNGER_MERGEINFO and then remove the older
684                  ranges from *MERGEINFO */
685               if (!(*younger_mergeinfo))
686                 *younger_mergeinfo = apr_hash_make(pool);
687               svn_hash_sets(*younger_mergeinfo, merge_source_path,
688                             younger_rangelist);
689               SVN_ERR(svn_mergeinfo_remove2(mergeinfo, *younger_mergeinfo,
690                                             *mergeinfo, TRUE, pool, iterpool));
691               break; /* ...out of for (i = 0; i < rangelist->nelts; i++) */
692             }
693         }
694     }
695
696   svn_pool_destroy(iterpool);
697
698   return SVN_NO_ERROR;
699 }
700
701
702 /* Make a copy of PROPCHANGES (array of svn_prop_t) into *TRIMMED_PROPCHANGES,
703    omitting any svn:mergeinfo changes.  */
704 static svn_error_t *
705 omit_mergeinfo_changes(apr_array_header_t **trimmed_propchanges,
706                        const apr_array_header_t *propchanges,
707                        apr_pool_t *result_pool)
708 {
709   int i;
710
711   *trimmed_propchanges = apr_array_make(result_pool,
712                                         propchanges->nelts,
713                                         sizeof(svn_prop_t));
714
715   for (i = 0; i < propchanges->nelts; ++i)
716     {
717       const svn_prop_t *change = &APR_ARRAY_IDX(propchanges, i, svn_prop_t);
718
719       /* If this property is not svn:mergeinfo, then copy it.  */
720       if (strcmp(change->name, SVN_PROP_MERGEINFO) != 0)
721         APR_ARRAY_PUSH(*trimmed_propchanges, svn_prop_t) = *change;
722     }
723
724   return SVN_NO_ERROR;
725 }
726
727
728 /* Helper for merge_props_changed().
729
730    *PROPS is an array of svn_prop_t structures representing regular properties
731    to be added to the working copy TARGET_ABSPATH.
732
733    The merge source and target are assumed to be in the same repository.
734
735    Filter out mergeinfo property additions to TARGET_ABSPATH when
736    those additions refer to the same line of history as TARGET_ABSPATH as
737    described below.
738
739    Examine the added mergeinfo, looking at each range (or single rev)
740    of each source path.  If a source_path/range refers to the same line of
741    history as TARGET_ABSPATH (pegged at its base revision), then filter out
742    that range.  If the entire rangelist for a given path is filtered then
743    filter out the path as well.
744
745    RA_SESSION is an open RA session to the repository
746    in which both the source and target live, else RA_SESSION is not used. It
747    may be temporarily reparented as needed by this function.
748
749    Use CTX for any further client operations.
750
751    If any filtering occurs, set outgoing *PROPS to a shallow copy (allocated
752    in POOL) of incoming *PROPS minus the filtered mergeinfo. */
753 static svn_error_t *
754 filter_self_referential_mergeinfo(apr_array_header_t **props,
755                                   const char *target_abspath,
756                                   svn_ra_session_t *ra_session,
757                                   svn_client_ctx_t *ctx,
758                                   apr_pool_t *pool)
759 {
760   apr_array_header_t *adjusted_props;
761   int i;
762   apr_pool_t *iterpool;
763   svn_boolean_t is_copy;
764   const char *repos_relpath;
765   svn_client__pathrev_t target_base;
766
767   /* If PATH itself has been added there is no need to filter. */
768   SVN_ERR(svn_wc__node_get_origin(&is_copy,  &target_base.rev, &repos_relpath,
769                                   &target_base.repos_root_url,
770                                   &target_base.repos_uuid, NULL, NULL,
771                                   ctx->wc_ctx, target_abspath, FALSE,
772                                   pool, pool));
773
774   if (is_copy || !repos_relpath)
775     return SVN_NO_ERROR; /* A copy or a local addition */
776
777   target_base.url = svn_path_url_add_component2(target_base.repos_root_url,
778                                                 repos_relpath, pool);
779
780   adjusted_props = apr_array_make(pool, (*props)->nelts, sizeof(svn_prop_t));
781   iterpool = svn_pool_create(pool);
782   for (i = 0; i < (*props)->nelts; ++i)
783     {
784       svn_prop_t *prop = &APR_ARRAY_IDX((*props), i, svn_prop_t);
785
786       svn_mergeinfo_t mergeinfo, younger_mergeinfo;
787       svn_mergeinfo_t filtered_mergeinfo = NULL;
788       svn_mergeinfo_t filtered_younger_mergeinfo = NULL;
789       svn_error_t *err;
790
791       /* If this property isn't mergeinfo or is NULL valued (i.e. prop removal)
792          or empty mergeinfo it does not require any special handling.  There
793          is nothing to filter out of empty mergeinfo and the concept of
794          filtering doesn't apply if we are trying to remove mergeinfo
795          entirely.  */
796       if ((strcmp(prop->name, SVN_PROP_MERGEINFO) != 0)
797           || (! prop->value)       /* Removal of mergeinfo */
798           || (! prop->value->len)) /* Empty mergeinfo */
799         {
800           APR_ARRAY_PUSH(adjusted_props, svn_prop_t) = *prop;
801           continue;
802         }
803
804       svn_pool_clear(iterpool);
805
806       /* Non-empty mergeinfo; filter self-referential mergeinfo out. */
807
808       /* Parse the incoming mergeinfo to allow easier manipulation. */
809       err = svn_mergeinfo_parse(&mergeinfo, prop->value->data, iterpool);
810
811       if (err)
812         {
813           /* Issue #3896: If we can't parse it, we certainly can't
814              filter it. */
815           if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
816             {
817               svn_error_clear(err);
818               APR_ARRAY_PUSH(adjusted_props, svn_prop_t) = *prop;
819               continue;
820             }
821           else
822             {
823               return svn_error_trace(err);
824             }
825         }
826
827       /* The working copy target PATH is at BASE_REVISION.  Divide the
828          incoming mergeinfo into two groups.  One where all revision ranges
829          are as old or older than BASE_REVISION and one where all revision
830          ranges are younger.
831
832          Note: You may be wondering why we do this.
833
834          For the incoming mergeinfo "older" than target's base revision we
835          can filter out self-referential mergeinfo efficiently using
836          svn_client__get_history_as_mergeinfo().  We simply look at PATH's
837          natural history as mergeinfo and remove that from any incoming
838          mergeinfo.
839
840          For mergeinfo "younger" than the base revision we can't use
841          svn_ra_get_location_segments() to look into PATH's future
842          history.  Instead we must use svn_client__repos_locations() and
843          look at each incoming source/range individually and see if PATH
844          at its base revision and PATH at the start of the incoming range
845          exist on the same line of history.  If they do then we can filter
846          out the incoming range.  But since we have to do this for each
847          range there is a substantial performance penalty to pay if the
848          incoming ranges are not contiguous, i.e. we call
849          svn_client__repos_locations for each discrete range and incur
850          the cost of a roundtrip communication with the repository. */
851       SVN_ERR(split_mergeinfo_on_revision(&younger_mergeinfo,
852                                           &mergeinfo,
853                                           target_base.rev,
854                                           iterpool));
855
856       /* Filter self-referential mergeinfo from younger_mergeinfo. */
857       if (younger_mergeinfo)
858         {
859           apr_hash_index_t *hi;
860           const char *merge_source_root_url;
861
862           SVN_ERR(svn_ra_get_repos_root2(ra_session,
863                                          &merge_source_root_url, iterpool));
864
865           for (hi = apr_hash_first(iterpool, younger_mergeinfo);
866                hi; hi = apr_hash_next(hi))
867             {
868               int j;
869               const char *source_path = apr_hash_this_key(hi);
870               svn_rangelist_t *rangelist = apr_hash_this_val(hi);
871               const char *merge_source_url;
872               svn_rangelist_t *adjusted_rangelist =
873                 apr_array_make(iterpool, 0, sizeof(svn_merge_range_t *));
874
875               merge_source_url =
876                     svn_path_url_add_component2(merge_source_root_url,
877                                                 source_path + 1, iterpool);
878
879               for (j = 0; j < rangelist->nelts; j++)
880                 {
881                   svn_error_t *err2;
882                   svn_client__pathrev_t *start_loc;
883                   svn_merge_range_t *range =
884                     APR_ARRAY_IDX(rangelist, j, svn_merge_range_t *);
885
886                   /* Because the merge source normalization code
887                      ensures mergeinfo refers to real locations on
888                      the same line of history, there's no need to
889                      look at the whole range, just the start. */
890
891                   /* Check if PATH@BASE_REVISION exists at
892                      RANGE->START on the same line of history.
893                      (start+1 because RANGE->start is not inclusive.) */
894                   err2 = svn_client__repos_location(&start_loc, ra_session,
895                                                     &target_base,
896                                                     range->start + 1,
897                                                     ctx, iterpool, iterpool);
898                   if (err2)
899                     {
900                       if (err2->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES
901                           || err2->apr_err == SVN_ERR_FS_NOT_FOUND
902                           || err2->apr_err == SVN_ERR_FS_NO_SUCH_REVISION)
903                         {
904                           /* PATH@BASE_REVISION didn't exist at
905                              RANGE->START + 1 or is unrelated to the
906                              resource PATH@RANGE->START.  Some of the
907                              requested revisions may not even exist in
908                              the repository; a real possibility since
909                              mergeinfo is hand editable.  In all of these
910                              cases clear and ignore the error and don't
911                              do any filtering.
912
913                              Note: In this last case it is possible that
914                              we will allow self-referential mergeinfo to
915                              be applied, but fixing it here is potentially
916                              very costly in terms of finding what part of
917                              a range is actually valid.  Simply allowing
918                              the merge to proceed without filtering the
919                              offending range seems the least worst
920                              option. */
921                           svn_error_clear(err2);
922                           err2 = NULL;
923                           APR_ARRAY_PUSH(adjusted_rangelist,
924                                          svn_merge_range_t *) = range;
925                         }
926                       else
927                         {
928                           return svn_error_trace(err2);
929                         }
930                      }
931                   else
932                     {
933                       /* PATH@BASE_REVISION exists on the same
934                          line of history at RANGE->START and RANGE->END.
935                          Now check that PATH@BASE_REVISION's path
936                          names at RANGE->START and RANGE->END are the same.
937                          If the names are not the same then the mergeinfo
938                          describing PATH@RANGE->START through
939                          PATH@RANGE->END actually belong to some other
940                          line of history and we want to record this
941                          mergeinfo, not filter it. */
942                       if (strcmp(start_loc->url, merge_source_url) != 0)
943                         {
944                           APR_ARRAY_PUSH(adjusted_rangelist,
945                                          svn_merge_range_t *) = range;
946                         }
947                     }
948                     /* else no need to add, this mergeinfo is
949                        all on the same line of history. */
950                 } /* for (j = 0; j < rangelist->nelts; j++) */
951
952               /* Add any rangelists for source_path that are not
953                  self-referential. */
954               if (adjusted_rangelist->nelts)
955                 {
956                   if (!filtered_younger_mergeinfo)
957                     filtered_younger_mergeinfo = apr_hash_make(iterpool);
958                   svn_hash_sets(filtered_younger_mergeinfo, source_path,
959                                 adjusted_rangelist);
960                 }
961
962             } /* Iteration over each merge source in younger_mergeinfo. */
963         } /* if (younger_mergeinfo) */
964
965       /* Filter self-referential mergeinfo from "older" mergeinfo. */
966       if (mergeinfo)
967         {
968           svn_mergeinfo_t implicit_mergeinfo;
969
970           SVN_ERR(svn_client__get_history_as_mergeinfo(
971             &implicit_mergeinfo, NULL,
972             &target_base, target_base.rev, SVN_INVALID_REVNUM,
973             ra_session, ctx, iterpool));
974
975           /* Remove PATH's implicit mergeinfo from the incoming mergeinfo. */
976           SVN_ERR(svn_mergeinfo_remove2(&filtered_mergeinfo,
977                                         implicit_mergeinfo,
978                                         mergeinfo, TRUE, iterpool, iterpool));
979         }
980
981       /* Combine whatever older and younger filtered mergeinfo exists
982          into filtered_mergeinfo. */
983       if (filtered_mergeinfo && filtered_younger_mergeinfo)
984         SVN_ERR(svn_mergeinfo_merge2(filtered_mergeinfo,
985                                      filtered_younger_mergeinfo, iterpool,
986                                      iterpool));
987       else if (filtered_younger_mergeinfo)
988         filtered_mergeinfo = filtered_younger_mergeinfo;
989
990       /* If there is any incoming mergeinfo remaining after filtering
991          then put it in adjusted_props. */
992       if (filtered_mergeinfo && apr_hash_count(filtered_mergeinfo))
993         {
994           /* Convert filtered_mergeinfo to a svn_prop_t and put it
995              back in the array. */
996           svn_string_t *filtered_mergeinfo_str;
997           svn_prop_t *adjusted_prop = apr_pcalloc(pool,
998                                                   sizeof(*adjusted_prop));
999           SVN_ERR(svn_mergeinfo_to_string(&filtered_mergeinfo_str,
1000                                           filtered_mergeinfo,
1001                                           pool));
1002           adjusted_prop->name = SVN_PROP_MERGEINFO;
1003           adjusted_prop->value = filtered_mergeinfo_str;
1004           APR_ARRAY_PUSH(adjusted_props, svn_prop_t) = *adjusted_prop;
1005         }
1006     }
1007   svn_pool_destroy(iterpool);
1008
1009   *props = adjusted_props;
1010   return SVN_NO_ERROR;
1011 }
1012
1013 /* Prepare a set of property changes PROPCHANGES to be used for a merge
1014    operation on LOCAL_ABSPATH.
1015
1016    Remove all non-regular prop-changes (entry-props and WC-props).
1017    Remove all non-mergeinfo prop-changes if it's a record-only merge.
1018    Remove self-referential mergeinfo (### in some cases...)
1019    Remove foreign-repository mergeinfo (### in some cases...)
1020
1021    Store the resulting property changes in *PROP_UPDATES.
1022    Store information on where mergeinfo is updated in MERGE_B.
1023
1024    Used for both file and directory property merges. */
1025 static svn_error_t *
1026 prepare_merge_props_changed(const apr_array_header_t **prop_updates,
1027                             const char *local_abspath,
1028                             const apr_array_header_t *propchanges,
1029                             merge_cmd_baton_t *merge_b,
1030                             apr_pool_t *result_pool,
1031                             apr_pool_t *scratch_pool)
1032 {
1033   apr_array_header_t *props;
1034
1035   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
1036
1037   /* We only want to merge "regular" version properties:  by
1038      definition, 'svn merge' shouldn't touch any data within .svn/  */
1039   SVN_ERR(svn_categorize_props(propchanges, NULL, NULL, &props,
1040                                result_pool));
1041
1042   /* If we are only applying mergeinfo changes then we need to do
1043      additional filtering of PROPS so it contains only mergeinfo changes. */
1044   if (merge_b->record_only && props->nelts)
1045     {
1046       apr_array_header_t *mergeinfo_props =
1047         apr_array_make(result_pool, 1, sizeof(svn_prop_t));
1048       int i;
1049
1050       for (i = 0; i < props->nelts; i++)
1051         {
1052           svn_prop_t *prop = &APR_ARRAY_IDX(props, i, svn_prop_t);
1053
1054           if (strcmp(prop->name, SVN_PROP_MERGEINFO) == 0)
1055             {
1056               APR_ARRAY_PUSH(mergeinfo_props, svn_prop_t) = *prop;
1057               break;
1058             }
1059         }
1060       props = mergeinfo_props;
1061     }
1062
1063   if (props->nelts)
1064     {
1065       /* Issue #3383: We don't want mergeinfo from a foreign repos.
1066
1067          If this is a merge from a foreign repository we must strip all
1068          incoming mergeinfo (including mergeinfo deletions). */
1069       if (! merge_b->same_repos)
1070         SVN_ERR(omit_mergeinfo_changes(&props, props, result_pool));
1071
1072       /* If this is a forward merge then don't add new mergeinfo to
1073          PATH that is already part of PATH's own history, see
1074          http://svn.haxx.se/dev/archive-2008-09/0006.shtml.  If the
1075          merge sources are not ancestral then there is no concept of a
1076          'forward' or 'reverse' merge and we filter unconditionally. */
1077       if (merge_b->merge_source.loc1->rev < merge_b->merge_source.loc2->rev
1078           || !merge_b->merge_source.ancestral)
1079         {
1080           if (HONOR_MERGEINFO(merge_b) || merge_b->reintegrate_merge)
1081             SVN_ERR(filter_self_referential_mergeinfo(&props,
1082                                                       local_abspath,
1083                                                       merge_b->ra_session2,
1084                                                       merge_b->ctx,
1085                                                       result_pool));
1086         }
1087     }
1088   *prop_updates = props;
1089
1090   /* Make a record in BATON if we find a PATH where mergeinfo is added
1091      where none existed previously or PATH is having its existing
1092      mergeinfo deleted. */
1093   if (props->nelts)
1094     {
1095       int i;
1096
1097       for (i = 0; i < props->nelts; ++i)
1098         {
1099           svn_prop_t *prop = &APR_ARRAY_IDX(props, i, svn_prop_t);
1100
1101           if (strcmp(prop->name, SVN_PROP_MERGEINFO) == 0)
1102             {
1103               /* Does LOCAL_ABSPATH have any pristine mergeinfo? */
1104               svn_boolean_t has_pristine_mergeinfo = FALSE;
1105               apr_hash_t *pristine_props;
1106
1107               SVN_ERR(svn_wc_get_pristine_props(&pristine_props,
1108                                                 merge_b->ctx->wc_ctx,
1109                                                 local_abspath,
1110                                                 scratch_pool,
1111                                                 scratch_pool));
1112
1113               if (pristine_props
1114                   && svn_hash_gets(pristine_props, SVN_PROP_MERGEINFO))
1115                 has_pristine_mergeinfo = TRUE;
1116
1117               if (!has_pristine_mergeinfo && prop->value)
1118                 {
1119                   alloc_and_store_path(&merge_b->paths_with_new_mergeinfo,
1120                                        local_abspath, merge_b->pool);
1121                 }
1122               else if (has_pristine_mergeinfo && !prop->value)
1123                 {
1124                   alloc_and_store_path(&merge_b->paths_with_deleted_mergeinfo,
1125                                        local_abspath, merge_b->pool);
1126                 }
1127             }
1128         }
1129     }
1130
1131   return SVN_NO_ERROR;
1132 }
1133
1134 #define CONFLICT_REASON_NONE       ((svn_wc_conflict_reason_t)-1)
1135 #define CONFLICT_REASON_SKIP       ((svn_wc_conflict_reason_t)-2)
1136 #define CONFLICT_REASON_SKIP_WC    ((svn_wc_conflict_reason_t)-3)
1137
1138 /* Baton used for testing trees for being editted while performing tree
1139    conflict detection for incoming deletes */
1140 struct dir_delete_baton_t
1141 {
1142   /* Reference to dir baton of directory that is the root of the deletion */
1143   struct merge_dir_baton_t *del_root;
1144
1145   /* Boolean indicating that some edit is found. Allows avoiding more work */
1146   svn_boolean_t found_edit;
1147
1148   /* A list of paths that are compared. Kept up to date until FOUND_EDIT is
1149      set to TRUE */
1150   apr_hash_t *compared_abspaths;
1151 };
1152
1153 /* Baton for the merge_dir_*() functions. Initialized in merge_dir_opened() */
1154 struct merge_dir_baton_t
1155 {
1156   /* Reference to the parent baton, unless the parent is the anchor, in which
1157      case PARENT_BATON is NULL */
1158   struct merge_dir_baton_t *parent_baton;
1159
1160   /* The pool containing this baton. Use for RESULT_POOL for storing in this
1161      baton */
1162   apr_pool_t *pool;
1163
1164   /* This directory doesn't have a representation in the working copy, so any
1165      operation on it will be skipped and possibly cause a tree conflict on the
1166      shadow root */
1167   svn_boolean_t shadowed;
1168
1169   /* This node or one of its descendants received operational changes from the
1170      merge. If this node is the shadow root its tree conflict status has been
1171      applied */
1172   svn_boolean_t edited;
1173
1174   /* If a tree conflict will be installed once edited, it's reason. If a skip
1175      should be produced its reason. Otherwise CONFLICT_REASON_NONE for no tree
1176      conflict.
1177
1178      Special values:
1179        CONFLICT_REASON_SKIP:
1180             The node will be skipped with content and property state as stored in
1181             SKIP_REASON.
1182
1183        CONFLICT_REASON_SKIP_WC:
1184             The node will be skipped as an obstructing working copy.
1185    */
1186   svn_wc_conflict_reason_t tree_conflict_reason;
1187   svn_wc_conflict_action_t tree_conflict_action;
1188   svn_node_kind_t tree_conflict_local_node_kind;
1189   svn_node_kind_t tree_conflict_merge_left_node_kind;
1190   svn_node_kind_t tree_conflict_merge_right_node_kind;
1191
1192   /* When TREE_CONFLICT_REASON is CONFLICT_REASON_SKIP, the skip state to
1193      add to the notification */
1194   svn_wc_notify_state_t skip_reason;
1195
1196   /* TRUE if the node was added by this merge. Otherwise FALSE */
1197   svn_boolean_t added;
1198   svn_boolean_t add_is_replace; /* Add is second part of replace */
1199
1200   /* TRUE if we are taking over an existing directory as addition, otherwise
1201      FALSE. */
1202   svn_boolean_t add_existing;
1203
1204   /* NULL, or an hashtable mapping const char * local_abspaths to
1205      const char *kind mapping, containing deleted nodes that still need a delete
1206      notification (which may be a replaced notification if the node is not just
1207      deleted) */
1208   apr_hash_t *pending_deletes;
1209
1210   /* NULL, or an hashtable mapping const char * LOCAL_ABSPATHs to
1211      a const svn_wc_conflict_description2_t * instance, describing the just
1212      installed conflict */
1213   apr_hash_t *new_tree_conflicts;
1214
1215   /* If not NULL, a reference to the information of the delete test that is
1216      currently in progress. Allocated in the root-directory baton, referenced
1217      from all descendants */
1218   struct dir_delete_baton_t *delete_state;
1219 };
1220
1221 /* Baton for the merge_dir_*() functions. Initialized in merge_file_opened() */
1222 struct merge_file_baton_t
1223 {
1224   /* Reference to the parent baton, unless the parent is the anchor, in which
1225      case PARENT_BATON is NULL */
1226   struct merge_dir_baton_t *parent_baton;
1227
1228   /* This file doesn't have a representation in the working copy, so any
1229      operation on it will be skipped and possibly cause a tree conflict
1230      on the shadow root */
1231   svn_boolean_t shadowed;
1232
1233   /* This node received operational changes from the merge. If this node
1234      is the shadow root its tree conflict status has been applied */
1235   svn_boolean_t edited;
1236
1237   /* If a tree conflict will be installed once edited, it's reason. If a skip
1238      should be produced its reason. Some special values are defined. See the
1239      merge_tree_baton_t for an explanation. */
1240   svn_wc_conflict_reason_t tree_conflict_reason;
1241   svn_wc_conflict_action_t tree_conflict_action;
1242   svn_node_kind_t tree_conflict_local_node_kind;
1243   svn_node_kind_t tree_conflict_merge_left_node_kind;
1244   svn_node_kind_t tree_conflict_merge_right_node_kind;
1245
1246   /* When TREE_CONFLICT_REASON is CONFLICT_REASON_SKIP, the skip state to
1247      add to the notification */
1248   svn_wc_notify_state_t skip_reason;
1249
1250   /* TRUE if the node was added by this merge. Otherwise FALSE */
1251   svn_boolean_t added;
1252   svn_boolean_t add_is_replace; /* Add is second part of replace */
1253 };
1254
1255 /* Forward declaration */
1256 static svn_error_t *
1257 notify_merge_begin(merge_cmd_baton_t *merge_b,
1258                    const char *local_abspath,
1259                    svn_boolean_t delete_action,
1260                    apr_pool_t *scratch_pool);
1261
1262 /* Record the skip for future processing and (later) produce the
1263    skip notification */
1264 static svn_error_t *
1265 record_skip(merge_cmd_baton_t *merge_b,
1266             const char *local_abspath,
1267             svn_node_kind_t kind,
1268             svn_wc_notify_action_t action,
1269             svn_wc_notify_state_t state,
1270             struct merge_dir_baton_t *pdb,
1271             apr_pool_t *scratch_pool)
1272 {
1273   if (merge_b->record_only)
1274     return SVN_NO_ERROR; /* ### Why? - Legacy compatibility */
1275
1276   if ((merge_b->merge_source.ancestral || merge_b->reintegrate_merge)
1277       && !(pdb && pdb->shadowed))
1278     {
1279       store_path(merge_b->skipped_abspaths, local_abspath);
1280     }
1281
1282   if (merge_b->ctx->notify_func2)
1283     {
1284       svn_wc_notify_t *notify;
1285
1286       SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE, scratch_pool));
1287
1288       notify = svn_wc_create_notify(local_abspath, action, scratch_pool);
1289       notify->kind = kind;
1290       notify->content_state = notify->prop_state = state;
1291
1292       merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2, notify,
1293                                  scratch_pool);
1294     }
1295   return SVN_NO_ERROR;
1296 }
1297
1298 /* Record a tree conflict in the WC, unless this is a dry run or a record-
1299  * only merge, or if a tree conflict is already flagged for the VICTIM_PATH.
1300  * (The latter can happen if a merge-tracking-aware merge is doing multiple
1301  * editor drives because of a gap in the range of eligible revisions.)
1302  *
1303  * The tree conflict, with its victim specified by VICTIM_PATH, is
1304  * assumed to have happened during a merge using merge baton MERGE_B.
1305  *
1306  * ACTION and REASON correspond to the fields
1307  * of the same names in svn_wc_tree_conflict_description_t.
1308  */
1309 static svn_error_t *
1310 record_tree_conflict(merge_cmd_baton_t *merge_b,
1311                      const char *local_abspath,
1312                      struct merge_dir_baton_t *parent_baton,
1313                      svn_node_kind_t local_node_kind,
1314                      svn_node_kind_t merge_left_node_kind,
1315                      svn_node_kind_t merge_right_node_kind,
1316                      svn_wc_conflict_action_t action,
1317                      svn_wc_conflict_reason_t reason,
1318                      const svn_wc_conflict_description2_t *existing_conflict,
1319                      svn_boolean_t notify_tc,
1320                      apr_pool_t *scratch_pool)
1321 {
1322   svn_wc_context_t *wc_ctx = merge_b->ctx->wc_ctx;
1323
1324   if (merge_b->record_only)
1325     return SVN_NO_ERROR;
1326
1327   if (merge_b->merge_source.ancestral
1328       || merge_b->reintegrate_merge)
1329     {
1330       store_path(merge_b->tree_conflicted_abspaths, local_abspath);
1331     }
1332
1333   alloc_and_store_path(&merge_b->conflicted_paths, local_abspath,
1334                        merge_b->pool);
1335
1336   if (!merge_b->dry_run)
1337     {
1338        svn_wc_conflict_description2_t *conflict;
1339        const svn_wc_conflict_version_t *left;
1340        const svn_wc_conflict_version_t *right;
1341        apr_pool_t *result_pool = parent_baton ? parent_baton->pool
1342                                               : scratch_pool;
1343
1344       if (reason == svn_wc_conflict_reason_deleted)
1345         {
1346           const char *moved_to_abspath;
1347
1348           SVN_ERR(svn_wc__node_was_moved_away(&moved_to_abspath, NULL,
1349                                               wc_ctx, local_abspath,
1350                                               scratch_pool, scratch_pool));
1351
1352           if (moved_to_abspath)
1353             {
1354               /* Local abspath itself has been moved away. If only a
1355                  descendant is moved away, we call the node itself deleted */
1356               reason = svn_wc_conflict_reason_moved_away;
1357             }
1358         }
1359       else if (reason == svn_wc_conflict_reason_added)
1360         {
1361           const char *moved_from_abspath;
1362           SVN_ERR(svn_wc__node_was_moved_here(&moved_from_abspath, NULL,
1363                                               wc_ctx, local_abspath,
1364                                               scratch_pool, scratch_pool));
1365           if (moved_from_abspath)
1366             reason = svn_wc_conflict_reason_moved_here;
1367         }
1368
1369       SVN_ERR(make_conflict_versions(&left, &right, local_abspath,
1370                                      merge_left_node_kind,
1371                                      merge_right_node_kind,
1372                                      &merge_b->merge_source, merge_b->target,
1373                                      result_pool, scratch_pool));
1374
1375       /* Fix up delete of file, add of dir replacement (or other way around) */
1376       if (existing_conflict != NULL && existing_conflict->src_left_version)
1377           left = existing_conflict->src_left_version;
1378
1379       conflict = svn_wc_conflict_description_create_tree2(
1380                         local_abspath, local_node_kind,
1381                         svn_wc_operation_merge,
1382                         left, right, result_pool);
1383
1384       conflict->action = action;
1385       conflict->reason = reason;
1386
1387       /* May return SVN_ERR_WC_PATH_UNEXPECTED_STATUS */
1388       if (existing_conflict)
1389         SVN_ERR(svn_wc__del_tree_conflict(wc_ctx, local_abspath,
1390                                           scratch_pool));
1391
1392       SVN_ERR(svn_wc__add_tree_conflict(merge_b->ctx->wc_ctx, conflict,
1393                                         scratch_pool));
1394
1395       if (parent_baton)
1396         {
1397           if (! parent_baton->new_tree_conflicts)
1398             parent_baton->new_tree_conflicts = apr_hash_make(result_pool);
1399
1400           svn_hash_sets(parent_baton->new_tree_conflicts,
1401                         apr_pstrdup(result_pool, local_abspath),
1402                         conflict);
1403         }
1404
1405       /* ### TODO: Store in parent baton */
1406     }
1407
1408   /* On a replacement we currently get two tree conflicts */
1409   if (merge_b->ctx->notify_func2 && notify_tc)
1410     {
1411       svn_wc_notify_t *notify;
1412
1413       SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE, scratch_pool));
1414
1415       notify = svn_wc_create_notify(local_abspath, svn_wc_notify_tree_conflict,
1416                                     scratch_pool);
1417       notify->kind = local_node_kind;
1418
1419       merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2, notify,
1420                                  scratch_pool);
1421     }
1422
1423   return SVN_NO_ERROR;
1424 }
1425
1426 /* Record the add for future processing and produce the
1427    update_add notification
1428  */
1429 static svn_error_t *
1430 record_update_add(merge_cmd_baton_t *merge_b,
1431                   const char *local_abspath,
1432                   svn_node_kind_t kind,
1433                   svn_boolean_t notify_replaced,
1434                   apr_pool_t *scratch_pool)
1435 {
1436   if (merge_b->merge_source.ancestral || merge_b->reintegrate_merge)
1437     {
1438       store_path(merge_b->merged_abspaths, local_abspath);
1439     }
1440
1441   if (merge_b->ctx->notify_func2)
1442     {
1443       svn_wc_notify_t *notify;
1444       svn_wc_notify_action_t action = svn_wc_notify_update_add;
1445
1446       SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE, scratch_pool));
1447
1448       if (notify_replaced)
1449         action = svn_wc_notify_update_replace;
1450
1451       notify = svn_wc_create_notify(local_abspath, action, scratch_pool);
1452       notify->kind = kind;
1453
1454       merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2, notify,
1455                                  scratch_pool);
1456     }
1457
1458   return SVN_NO_ERROR;
1459 }
1460
1461 /* Record the update for future processing and produce the
1462    update_update notification */
1463 static svn_error_t *
1464 record_update_update(merge_cmd_baton_t *merge_b,
1465                      const char *local_abspath,
1466                      svn_node_kind_t kind,
1467                      svn_wc_notify_state_t content_state,
1468                      svn_wc_notify_state_t prop_state,
1469                      apr_pool_t *scratch_pool)
1470 {
1471   if (merge_b->merge_source.ancestral || merge_b->reintegrate_merge)
1472     {
1473       store_path(merge_b->merged_abspaths, local_abspath);
1474     }
1475
1476   if (merge_b->ctx->notify_func2)
1477     {
1478       svn_wc_notify_t *notify;
1479
1480       SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE, scratch_pool));
1481
1482       notify = svn_wc_create_notify(local_abspath, svn_wc_notify_update_update,
1483                                     scratch_pool);
1484       notify->kind = kind;
1485       notify->content_state = content_state;
1486       notify->prop_state = prop_state;
1487
1488       merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2, notify,
1489                                  scratch_pool);
1490     }
1491
1492   return SVN_NO_ERROR;
1493 }
1494
1495 /* Record the delete for future processing and for (later) producing the
1496    update_delete notification */
1497 static svn_error_t *
1498 record_update_delete(merge_cmd_baton_t *merge_b,
1499                      struct merge_dir_baton_t *parent_db,
1500                      const char *local_abspath,
1501                      svn_node_kind_t kind,
1502                      apr_pool_t *scratch_pool)
1503 {
1504   /* Update the lists of merged, skipped, tree-conflicted and added paths. */
1505   if (merge_b->merge_source.ancestral
1506       || merge_b->reintegrate_merge)
1507     {
1508       /* Issue #4166: If a previous merge added NOTIFY_ABSPATH, but we
1509          are now deleting it, then remove it from the list of added
1510          paths. */
1511       svn_hash_sets(merge_b->added_abspaths, local_abspath, NULL);
1512       store_path(merge_b->merged_abspaths, local_abspath);
1513     }
1514
1515   SVN_ERR(notify_merge_begin(merge_b, local_abspath, TRUE, scratch_pool));
1516
1517   if (parent_db)
1518     {
1519       const char *dup_abspath = apr_pstrdup(parent_db->pool, local_abspath);
1520
1521       if (!parent_db->pending_deletes)
1522         parent_db->pending_deletes = apr_hash_make(parent_db->pool);
1523
1524       svn_hash_sets(parent_db->pending_deletes, dup_abspath,
1525                     svn_node_kind_to_word(kind));
1526     }
1527
1528   return SVN_NO_ERROR;
1529 }
1530
1531 /* Notify the pending 'D'eletes, that were waiting to see if a matching 'A'dd
1532    might make them a 'R'eplace. */
1533 static svn_error_t *
1534 handle_pending_notifications(merge_cmd_baton_t *merge_b,
1535                              struct merge_dir_baton_t *db,
1536                              apr_pool_t *scratch_pool)
1537 {
1538   if (merge_b->ctx->notify_func2 && db->pending_deletes)
1539     {
1540       apr_hash_index_t *hi;
1541
1542       for (hi = apr_hash_first(scratch_pool, db->pending_deletes);
1543            hi;
1544            hi = apr_hash_next(hi))
1545         {
1546           const char *del_abspath = apr_hash_this_key(hi);
1547           svn_wc_notify_t *notify;
1548
1549           notify = svn_wc_create_notify(del_abspath,
1550                                         svn_wc_notify_update_delete,
1551                                         scratch_pool);
1552           notify->kind = svn_node_kind_from_word(
1553                                     apr_hash_this_val(hi));
1554
1555           merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2,
1556                                      notify, scratch_pool);
1557         }
1558
1559       db->pending_deletes = NULL;
1560     }
1561   return SVN_NO_ERROR;
1562 }
1563
1564 /* Helper function for the merge_dir_*() and merge_file_*() functions.
1565
1566    Installs and notifies pre-recorded tree conflicts and skips for
1567    ancestors of operational merges
1568  */
1569 static svn_error_t *
1570 mark_dir_edited(merge_cmd_baton_t *merge_b,
1571                 struct merge_dir_baton_t *db,
1572                 const char *local_abspath,
1573                 apr_pool_t *scratch_pool)
1574 {
1575   /* ### Too much common code with mark_file_edited */
1576   if (db->edited)
1577     return SVN_NO_ERROR;
1578
1579   if (db->parent_baton && !db->parent_baton->edited)
1580     {
1581       const char *dir_abspath = svn_dirent_dirname(local_abspath,
1582                                                    scratch_pool);
1583
1584       SVN_ERR(mark_dir_edited(merge_b, db->parent_baton, dir_abspath,
1585                               scratch_pool));
1586     }
1587
1588   db->edited = TRUE;
1589
1590   if (! db->shadowed)
1591     return SVN_NO_ERROR; /* Easy out */
1592
1593   if (db->parent_baton
1594       && db->parent_baton->delete_state
1595       && db->tree_conflict_reason != CONFLICT_REASON_NONE)
1596     {
1597       db->parent_baton->delete_state->found_edit = TRUE;
1598     }
1599   else if (db->tree_conflict_reason == CONFLICT_REASON_SKIP
1600            || db->tree_conflict_reason == CONFLICT_REASON_SKIP_WC)
1601     {
1602       /* open_directory() decided not to flag a tree conflict, but
1603          for clarity we produce a skip for this node that
1604          most likely isn't touched by the merge itself */
1605
1606       if (merge_b->ctx->notify_func2)
1607         {
1608           svn_wc_notify_t *notify;
1609
1610           SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE,
1611                                      scratch_pool));
1612
1613           notify = svn_wc_create_notify(
1614                             local_abspath,
1615                             (db->tree_conflict_reason == CONFLICT_REASON_SKIP)
1616                                 ? svn_wc_notify_skip
1617                                 : svn_wc_notify_update_skip_obstruction,
1618                             scratch_pool);
1619           notify->kind = svn_node_dir;
1620           notify->content_state = notify->prop_state = db->skip_reason;
1621
1622           merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2,
1623                                      notify,
1624                                      scratch_pool);
1625         }
1626
1627       if (merge_b->merge_source.ancestral
1628           || merge_b->reintegrate_merge)
1629         {
1630           store_path(merge_b->skipped_abspaths, local_abspath);
1631         }
1632     }
1633   else if (db->tree_conflict_reason != CONFLICT_REASON_NONE)
1634     {
1635       /* open_directory() decided that a tree conflict should be raised */
1636
1637       SVN_ERR(record_tree_conflict(merge_b, local_abspath, db->parent_baton,
1638                                    db->tree_conflict_local_node_kind,
1639                                    db->tree_conflict_merge_left_node_kind,
1640                                    db->tree_conflict_merge_right_node_kind,
1641                                    db->tree_conflict_action,
1642                                    db->tree_conflict_reason,
1643                                    NULL, TRUE,
1644                                    scratch_pool));
1645     }
1646
1647   return SVN_NO_ERROR;
1648 }
1649
1650 /* Helper function for the merge_file_*() functions.
1651
1652    Installs and notifies pre-recorded tree conflicts and skips for
1653    ancestors of operational merges
1654  */
1655 static svn_error_t *
1656 mark_file_edited(merge_cmd_baton_t *merge_b,
1657                  struct merge_file_baton_t *fb,
1658                  const char *local_abspath,
1659                  apr_pool_t *scratch_pool)
1660 {
1661   /* ### Too much common code with mark_dir_edited */
1662   if (fb->edited)
1663     return SVN_NO_ERROR;
1664
1665   if (fb->parent_baton && !fb->parent_baton->edited)
1666     {
1667       const char *dir_abspath = svn_dirent_dirname(local_abspath,
1668                                                    scratch_pool);
1669
1670       SVN_ERR(mark_dir_edited(merge_b, fb->parent_baton, dir_abspath,
1671                               scratch_pool));
1672     }
1673
1674   fb->edited = TRUE;
1675
1676   if (! fb->shadowed)
1677     return SVN_NO_ERROR; /* Easy out */
1678
1679   if (fb->parent_baton
1680       && fb->parent_baton->delete_state
1681       && fb->tree_conflict_reason != CONFLICT_REASON_NONE)
1682     {
1683       fb->parent_baton->delete_state->found_edit = TRUE;
1684     }
1685   else if (fb->tree_conflict_reason == CONFLICT_REASON_SKIP
1686            || fb->tree_conflict_reason == CONFLICT_REASON_SKIP_WC)
1687     {
1688       /* open_directory() decided not to flag a tree conflict, but
1689          for clarity we produce a skip for this node that
1690          most likely isn't touched by the merge itself */
1691
1692       if (merge_b->ctx->notify_func2)
1693         {
1694           svn_wc_notify_t *notify;
1695
1696           SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE,
1697                                      scratch_pool));
1698
1699           notify = svn_wc_create_notify(local_abspath, svn_wc_notify_skip,
1700                                         scratch_pool);
1701           notify->kind = svn_node_file;
1702           notify->content_state = notify->prop_state = fb->skip_reason;
1703
1704           merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2,
1705                                      notify,
1706                                      scratch_pool);
1707         }
1708
1709       if (merge_b->merge_source.ancestral
1710           || merge_b->reintegrate_merge)
1711         {
1712           store_path(merge_b->skipped_abspaths, local_abspath);
1713         }
1714     }
1715   else if (fb->tree_conflict_reason != CONFLICT_REASON_NONE)
1716     {
1717       /* open_file() decided that a tree conflict should be raised */
1718
1719       SVN_ERR(record_tree_conflict(merge_b, local_abspath, fb->parent_baton,
1720                                    fb->tree_conflict_local_node_kind,
1721                                    fb->tree_conflict_merge_left_node_kind,
1722                                    fb->tree_conflict_merge_right_node_kind,
1723                                    fb->tree_conflict_action,
1724                                    fb->tree_conflict_reason,
1725                                    NULL, TRUE,
1726                                    scratch_pool));
1727     }
1728
1729   return SVN_NO_ERROR;
1730 }
1731
1732 /* An svn_diff_tree_processor_t function.
1733
1734    Called before either merge_file_changed(), merge_file_added(),
1735    merge_file_deleted() or merge_file_closed(), unless it sets *SKIP to TRUE.
1736
1737    When *SKIP is TRUE, the diff driver avoids work on getting the details
1738    for the closing callbacks.
1739  */
1740 static svn_error_t *
1741 merge_file_opened(void **new_file_baton,
1742                   svn_boolean_t *skip,
1743                   const char *relpath,
1744                   const svn_diff_source_t *left_source,
1745                   const svn_diff_source_t *right_source,
1746                   const svn_diff_source_t *copyfrom_source,
1747                   void *dir_baton,
1748                   const struct svn_diff_tree_processor_t *processor,
1749                   apr_pool_t *result_pool,
1750                   apr_pool_t *scratch_pool)
1751 {
1752   merge_cmd_baton_t *merge_b = processor->baton;
1753   struct merge_dir_baton_t *pdb = dir_baton;
1754   struct merge_file_baton_t *fb;
1755   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
1756                                               relpath, scratch_pool);
1757
1758   fb = apr_pcalloc(result_pool, sizeof(*fb));
1759   fb->tree_conflict_reason = CONFLICT_REASON_NONE;
1760   fb->tree_conflict_action = svn_wc_conflict_action_edit;
1761   fb->skip_reason = svn_wc_notify_state_unknown;
1762
1763   if (left_source)
1764     fb->tree_conflict_merge_left_node_kind = svn_node_file;
1765   else
1766     fb->tree_conflict_merge_left_node_kind = svn_node_none;
1767
1768   if (right_source)
1769     fb->tree_conflict_merge_right_node_kind = svn_node_file;
1770   else
1771     fb->tree_conflict_merge_right_node_kind = svn_node_none;
1772
1773   *new_file_baton = fb;
1774
1775   if (pdb)
1776     {
1777       fb->parent_baton = pdb;
1778       fb->shadowed = pdb->shadowed;
1779       fb->skip_reason = pdb->skip_reason;
1780     }
1781
1782   if (fb->shadowed)
1783     {
1784       /* An ancestor is tree conflicted. Nothing to do here. */
1785     }
1786   else if (left_source != NULL)
1787     {
1788       /* Node is expected to be a file, which will be changed or deleted. */
1789       svn_boolean_t is_deleted;
1790       svn_boolean_t excluded;
1791       svn_depth_t parent_depth;
1792
1793       if (! right_source)
1794         fb->tree_conflict_action = svn_wc_conflict_action_delete;
1795
1796       {
1797         svn_wc_notify_state_t obstr_state;
1798
1799         SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, &excluded,
1800                                           &fb->tree_conflict_local_node_kind,
1801                                           &parent_depth,
1802                                           merge_b, local_abspath,
1803                                           scratch_pool));
1804
1805         if (obstr_state != svn_wc_notify_state_inapplicable)
1806           {
1807             fb->shadowed = TRUE;
1808             fb->tree_conflict_reason = CONFLICT_REASON_SKIP;
1809             fb->skip_reason = obstr_state;
1810             return SVN_NO_ERROR;
1811           }
1812
1813         if (is_deleted)
1814           fb->tree_conflict_local_node_kind = svn_node_none;
1815       }
1816
1817       if (fb->tree_conflict_local_node_kind == svn_node_none)
1818         {
1819           fb->shadowed = TRUE;
1820
1821           /* If this is not the merge target and the parent is too shallow to
1822              contain this directory, and the directory is not present
1823              via exclusion or depth filtering, skip it instead of recording
1824              a tree conflict.
1825
1826              Non-inheritable mergeinfo will be recorded, allowing
1827              future merges into non-shallow working copies to merge
1828              changes we missed this time around. */
1829           if (pdb && (excluded
1830                       || (parent_depth != svn_depth_unknown &&
1831                           parent_depth < svn_depth_files)))
1832             {
1833                 fb->shadowed = TRUE;
1834
1835                 fb->tree_conflict_reason = CONFLICT_REASON_SKIP;
1836                 fb->skip_reason = svn_wc_notify_state_missing;
1837                 return SVN_NO_ERROR;
1838             }
1839
1840           if (is_deleted)
1841             fb->tree_conflict_reason = svn_wc_conflict_reason_deleted;
1842           else
1843             fb->tree_conflict_reason = svn_wc_conflict_reason_missing;
1844
1845           /* ### Similar to directory */
1846           *skip = TRUE;
1847           SVN_ERR(mark_file_edited(merge_b, fb, local_abspath, scratch_pool));
1848           return SVN_NO_ERROR;
1849           /* ### /Similar */
1850         }
1851       else if (fb->tree_conflict_local_node_kind != svn_node_file)
1852         {
1853           svn_boolean_t added;
1854           fb->shadowed = TRUE;
1855
1856           SVN_ERR(svn_wc__node_is_added(&added, merge_b->ctx->wc_ctx,
1857                                         local_abspath, scratch_pool));
1858
1859           fb->tree_conflict_reason = added ? svn_wc_conflict_reason_added
1860                                            : svn_wc_conflict_reason_obstructed;
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
1869       if (! right_source)
1870         {
1871           /* We want to delete the directory */
1872           fb->tree_conflict_action = svn_wc_conflict_action_delete;
1873           SVN_ERR(mark_file_edited(merge_b, fb, local_abspath, scratch_pool));
1874
1875           if (fb->shadowed)
1876             {
1877               return SVN_NO_ERROR; /* Already set a tree conflict */
1878             }
1879
1880           /* Comparison mode to verify for delete tree conflicts? */
1881           if (pdb && pdb->delete_state
1882               && pdb->delete_state->found_edit)
1883             {
1884               /* Earlier nodes found a conflict. Done. */
1885               *skip = TRUE;
1886             }
1887         }
1888     }
1889   else
1890     {
1891       const svn_wc_conflict_description2_t *old_tc = NULL;
1892
1893       /* The node doesn't exist pre-merge: We have an addition */
1894       fb->added = TRUE;
1895       fb->tree_conflict_action = svn_wc_conflict_action_add;
1896
1897       if (pdb && pdb->pending_deletes
1898           && svn_hash_gets(pdb->pending_deletes, local_abspath))
1899         {
1900           fb->add_is_replace = TRUE;
1901           fb->tree_conflict_action = svn_wc_conflict_action_replace;
1902
1903           svn_hash_sets(pdb->pending_deletes, local_abspath, NULL);
1904         }
1905
1906       if (pdb
1907           && pdb->new_tree_conflicts
1908           && (old_tc = svn_hash_gets(pdb->new_tree_conflicts, local_abspath)))
1909         {
1910           fb->tree_conflict_action = svn_wc_conflict_action_replace;
1911           fb->tree_conflict_reason = old_tc->reason;
1912
1913           /* Update the tree conflict to store that this is a replace */
1914           SVN_ERR(record_tree_conflict(merge_b, local_abspath, pdb,
1915                                        old_tc->node_kind,
1916                                        old_tc->src_left_version->node_kind,
1917                                        svn_node_file,
1918                                        fb->tree_conflict_action,
1919                                        fb->tree_conflict_reason,
1920                                        old_tc, FALSE,
1921                                        scratch_pool));
1922
1923           if (old_tc->reason == svn_wc_conflict_reason_deleted
1924               || old_tc->reason == svn_wc_conflict_reason_moved_away)
1925             {
1926               /* Issue #3806: Incoming replacements on local deletes produce
1927                  inconsistent result.
1928
1929                  In this specific case we can continue applying the add part
1930                  of the replacement. */
1931             }
1932           else
1933             {
1934               *skip = TRUE;
1935
1936               return SVN_NO_ERROR;
1937             }
1938         }
1939       else if (! (merge_b->dry_run
1940                   && ((pdb && pdb->added) || fb->add_is_replace)))
1941         {
1942           svn_wc_notify_state_t obstr_state;
1943           svn_boolean_t is_deleted;
1944
1945           SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, NULL,
1946                                             &fb->tree_conflict_local_node_kind,
1947                                             NULL, merge_b, local_abspath,
1948                                             scratch_pool));
1949
1950           if (obstr_state != svn_wc_notify_state_inapplicable)
1951             {
1952               /* Skip the obstruction */
1953               fb->shadowed = TRUE;
1954               fb->tree_conflict_reason = CONFLICT_REASON_SKIP;
1955               fb->skip_reason = obstr_state;
1956             }
1957           else if (fb->tree_conflict_local_node_kind != svn_node_none
1958                    && !is_deleted)
1959             {
1960               /* Set a tree conflict */
1961               svn_boolean_t added;
1962
1963               fb->shadowed = TRUE;
1964               SVN_ERR(svn_wc__node_is_added(&added, merge_b->ctx->wc_ctx,
1965                                             local_abspath, scratch_pool));
1966
1967               fb->tree_conflict_reason = added ? svn_wc_conflict_reason_added
1968                                                : svn_wc_conflict_reason_obstructed;
1969             }
1970         }
1971
1972       /* Handle pending conflicts */
1973       SVN_ERR(mark_file_edited(merge_b, fb, local_abspath, scratch_pool));
1974     }
1975
1976   return SVN_NO_ERROR;
1977 }
1978
1979 /* An svn_diff_tree_processor_t function.
1980  *
1981  * Called after merge_file_opened() when a node receives only text and/or
1982  * property changes between LEFT_SOURCE and RIGHT_SOURCE.
1983  *
1984  * left_file and right_file can be NULL when the file is not modified.
1985  * left_props and right_props are always available.
1986  */
1987 static svn_error_t *
1988 merge_file_changed(const char *relpath,
1989                   const svn_diff_source_t *left_source,
1990                   const svn_diff_source_t *right_source,
1991                   const char *left_file,
1992                   const char *right_file,
1993                   /*const*/ apr_hash_t *left_props,
1994                   /*const*/ apr_hash_t *right_props,
1995                   svn_boolean_t file_modified,
1996                   const apr_array_header_t *prop_changes,
1997                   void *file_baton,
1998                   const struct svn_diff_tree_processor_t *processor,
1999                   apr_pool_t *scratch_pool)
2000 {
2001   merge_cmd_baton_t *merge_b = processor->baton;
2002   struct merge_file_baton_t *fb = file_baton;
2003   svn_client_ctx_t *ctx = merge_b->ctx;
2004   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
2005                                               relpath, scratch_pool);
2006   const svn_wc_conflict_version_t *left;
2007   const svn_wc_conflict_version_t *right;
2008   svn_wc_notify_state_t text_state;
2009   svn_wc_notify_state_t property_state;
2010
2011   SVN_ERR_ASSERT(local_abspath && svn_dirent_is_absolute(local_abspath));
2012   SVN_ERR_ASSERT(!left_file || svn_dirent_is_absolute(left_file));
2013   SVN_ERR_ASSERT(!right_file || svn_dirent_is_absolute(right_file));
2014
2015   SVN_ERR(mark_file_edited(merge_b, fb, local_abspath, scratch_pool));
2016
2017   if (fb->shadowed)
2018     {
2019       if (fb->tree_conflict_reason == CONFLICT_REASON_NONE)
2020         {
2021           /* We haven't notified for this node yet: report a skip */
2022           SVN_ERR(record_skip(merge_b, local_abspath, svn_node_file,
2023                               svn_wc_notify_update_shadowed_update,
2024                               fb->skip_reason, fb->parent_baton,
2025                               scratch_pool));
2026         }
2027
2028       return SVN_NO_ERROR;
2029     }
2030
2031   /* This callback is essentially no more than a wrapper around
2032      svn_wc_merge5().  Thank goodness that all the
2033      diff-editor-mechanisms are doing the hard work of getting the
2034      fulltexts! */
2035
2036   property_state = svn_wc_notify_state_unchanged;
2037   text_state = svn_wc_notify_state_unchanged;
2038
2039   SVN_ERR(prepare_merge_props_changed(&prop_changes, local_abspath,
2040                                       prop_changes, merge_b,
2041                                       scratch_pool, scratch_pool));
2042
2043   SVN_ERR(make_conflict_versions(&left, &right, local_abspath,
2044                                  svn_node_file, svn_node_file,
2045                                  &merge_b->merge_source, merge_b->target,
2046                                  scratch_pool, scratch_pool));
2047
2048   /* Do property merge now, if we are not going to perform a text merge */
2049   if ((merge_b->record_only || !left_file) && prop_changes->nelts)
2050     {
2051       SVN_ERR(svn_wc_merge_props3(&property_state, ctx->wc_ctx, local_abspath,
2052                                   left, right,
2053                                   left_props, prop_changes,
2054                                   merge_b->dry_run,
2055                                   NULL, NULL,
2056                                   ctx->cancel_func, ctx->cancel_baton,
2057                                   scratch_pool));
2058       if (property_state == svn_wc_notify_state_conflicted)
2059         {
2060           alloc_and_store_path(&merge_b->conflicted_paths, local_abspath,
2061                                merge_b->pool);
2062         }
2063     }
2064
2065   /* Easy out: We are only applying mergeinfo differences. */
2066   if (merge_b->record_only)
2067     {
2068       /* NO-OP */
2069     }
2070   else if (left_file)
2071     {
2072       svn_boolean_t has_local_mods;
2073       enum svn_wc_merge_outcome_t content_outcome;
2074       const char *target_label;
2075       const char *left_label;
2076       const char *right_label;
2077       const char *path_ext = "";
2078
2079       if (merge_b->ext_patterns && merge_b->ext_patterns->nelts)
2080         {
2081           svn_path_splitext(NULL, &path_ext, local_abspath, scratch_pool);
2082           if (! (*path_ext
2083                  && svn_cstring_match_glob_list(path_ext,
2084                                                 merge_b->ext_patterns)))
2085             {
2086               path_ext = "";
2087             }
2088         }
2089
2090       /* xgettext: the '.working', '.merge-left.r%ld' and
2091          '.merge-right.r%ld' strings are used to tag onto a file
2092          name in case of a merge conflict */
2093
2094       target_label = apr_psprintf(scratch_pool, _(".working%s%s"),
2095                                   *path_ext ? "." : "", path_ext);
2096       left_label = apr_psprintf(scratch_pool,
2097                                 _(".merge-left.r%ld%s%s"),
2098                                 left_source->revision,
2099                                 *path_ext ? "." : "", path_ext);
2100       right_label = apr_psprintf(scratch_pool,
2101                                  _(".merge-right.r%ld%s%s"),
2102                                  right_source->revision,
2103                                  *path_ext ? "." : "", path_ext);
2104
2105       SVN_ERR(svn_wc_text_modified_p2(&has_local_mods, ctx->wc_ctx,
2106                                       local_abspath, FALSE, scratch_pool));
2107
2108       /* Do property merge and text merge in one step so that keyword expansion
2109          takes into account the new property values. */
2110       SVN_ERR(svn_wc_merge5(&content_outcome, &property_state, ctx->wc_ctx,
2111                             left_file, right_file, local_abspath,
2112                             left_label, right_label, target_label,
2113                             left, right,
2114                             merge_b->dry_run, merge_b->diff3_cmd,
2115                             merge_b->merge_options,
2116                             left_props, prop_changes,
2117                             NULL, NULL,
2118                             ctx->cancel_func,
2119                             ctx->cancel_baton,
2120                             scratch_pool));
2121
2122       if (content_outcome == svn_wc_merge_conflict
2123           || property_state == svn_wc_notify_state_conflicted)
2124         {
2125           alloc_and_store_path(&merge_b->conflicted_paths, local_abspath,
2126                                merge_b->pool);
2127         }
2128
2129       if (content_outcome == svn_wc_merge_conflict)
2130         text_state = svn_wc_notify_state_conflicted;
2131       else if (has_local_mods
2132                && content_outcome != svn_wc_merge_unchanged)
2133         text_state = svn_wc_notify_state_merged;
2134       else if (content_outcome == svn_wc_merge_merged)
2135         text_state = svn_wc_notify_state_changed;
2136       else if (content_outcome == svn_wc_merge_no_merge)
2137         text_state = svn_wc_notify_state_missing;
2138       else /* merge_outcome == svn_wc_merge_unchanged */
2139         text_state = svn_wc_notify_state_unchanged;
2140     }
2141
2142   if (text_state == svn_wc_notify_state_conflicted
2143       || text_state == svn_wc_notify_state_merged
2144       || text_state == svn_wc_notify_state_changed
2145       || property_state == svn_wc_notify_state_conflicted
2146       || property_state == svn_wc_notify_state_merged
2147       || property_state == svn_wc_notify_state_changed)
2148     {
2149       SVN_ERR(record_update_update(merge_b, local_abspath, svn_node_file,
2150                                    text_state, property_state,
2151                                    scratch_pool));
2152     }
2153
2154   return SVN_NO_ERROR;
2155 }
2156
2157 /* An svn_diff_tree_processor_t function.
2158  *
2159  * Called after merge_file_opened() when a node doesn't exist in LEFT_SOURCE,
2160  * but does in RIGHT_SOURCE.
2161  *
2162  * When a node is replaced instead of just added a separate opened+deleted will
2163  * be invoked before the current open+added.
2164  */
2165 static svn_error_t *
2166 merge_file_added(const char *relpath,
2167                  const svn_diff_source_t *copyfrom_source,
2168                  const svn_diff_source_t *right_source,
2169                  const char *copyfrom_file,
2170                  const char *right_file,
2171                  /*const*/ apr_hash_t *copyfrom_props,
2172                  /*const*/ apr_hash_t *right_props,
2173                  void *file_baton,
2174                  const struct svn_diff_tree_processor_t *processor,
2175                  apr_pool_t *scratch_pool)
2176 {
2177   merge_cmd_baton_t *merge_b = processor->baton;
2178   struct merge_file_baton_t *fb = file_baton;
2179   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
2180                                               relpath, scratch_pool);
2181   apr_hash_t *pristine_props;
2182   apr_hash_t *new_props;
2183
2184   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
2185
2186   SVN_ERR(mark_file_edited(merge_b, fb, local_abspath, scratch_pool));
2187
2188   if (fb->shadowed)
2189     {
2190       if (fb->tree_conflict_reason == CONFLICT_REASON_NONE)
2191         {
2192           /* We haven't notified for this node yet: report a skip */
2193           SVN_ERR(record_skip(merge_b, local_abspath, svn_node_file,
2194                               svn_wc_notify_update_shadowed_add,
2195                               fb->skip_reason, fb->parent_baton,
2196                               scratch_pool));
2197         }
2198
2199       return SVN_NO_ERROR;
2200     }
2201
2202   /* Easy out: We are only applying mergeinfo differences. */
2203   if (merge_b->record_only)
2204     {
2205       return SVN_NO_ERROR;
2206     }
2207
2208   if ((merge_b->merge_source.ancestral || merge_b->reintegrate_merge)
2209       && ( !fb->parent_baton || !fb->parent_baton->added))
2210     {
2211       /* Store the roots of added subtrees */
2212       store_path(merge_b->added_abspaths, local_abspath);
2213     }
2214
2215   if (!merge_b->dry_run)
2216     {
2217       const char *copyfrom_url;
2218       svn_revnum_t copyfrom_rev;
2219       svn_stream_t *new_contents, *pristine_contents;
2220
2221       /* If this is a merge from the same repository as our
2222          working copy, we handle adds as add-with-history.
2223          Otherwise, we'll use a pure add. */
2224       if (merge_b->same_repos)
2225         {
2226           const char *child =
2227             svn_dirent_skip_ancestor(merge_b->target->abspath,
2228                                      local_abspath);
2229           SVN_ERR_ASSERT(child != NULL);
2230           copyfrom_url = svn_path_url_add_component2(
2231                                        merge_b->merge_source.loc2->url,
2232                                        child, scratch_pool);
2233           copyfrom_rev = right_source->revision;
2234           SVN_ERR(check_repos_match(merge_b->target, local_abspath,
2235                                     copyfrom_url, scratch_pool));
2236           SVN_ERR(svn_stream_open_readonly(&pristine_contents,
2237                                            right_file,
2238                                            scratch_pool,
2239                                            scratch_pool));
2240           new_contents = NULL; /* inherit from new_base_contents */
2241
2242           pristine_props = right_props; /* Includes last_* information */
2243           new_props = NULL; /* No local changes */
2244
2245           if (svn_hash_gets(pristine_props, SVN_PROP_MERGEINFO))
2246             {
2247               alloc_and_store_path(&merge_b->paths_with_new_mergeinfo,
2248                                    local_abspath, merge_b->pool);
2249             }
2250         }
2251       else
2252         {
2253           apr_array_header_t *regular_props;
2254
2255           copyfrom_url = NULL;
2256           copyfrom_rev = SVN_INVALID_REVNUM;
2257
2258           pristine_contents = svn_stream_empty(scratch_pool);
2259           SVN_ERR(svn_stream_open_readonly(&new_contents, right_file,
2260                                            scratch_pool, scratch_pool));
2261
2262           pristine_props = apr_hash_make(scratch_pool); /* Local addition */
2263
2264           /* We don't want any foreign properties */
2265           SVN_ERR(svn_categorize_props(svn_prop_hash_to_array(right_props,
2266                                                               scratch_pool),
2267                                        NULL, NULL, &regular_props,
2268                                        scratch_pool));
2269
2270           new_props = svn_prop_array_to_hash(regular_props, scratch_pool);
2271
2272           /* Issue #3383: We don't want mergeinfo from a foreign repository. */
2273           svn_hash_sets(new_props, SVN_PROP_MERGEINFO, NULL);
2274         }
2275
2276       /* Do everything like if we had called 'svn cp PATH1 PATH2'. */
2277       SVN_ERR(svn_wc_add_repos_file4(merge_b->ctx->wc_ctx,
2278                                       local_abspath,
2279                                       pristine_contents,
2280                                       new_contents,
2281                                       pristine_props, new_props,
2282                                       copyfrom_url, copyfrom_rev,
2283                                       merge_b->ctx->cancel_func,
2284                                       merge_b->ctx->cancel_baton,
2285                                       scratch_pool));
2286
2287       /* Caller must call svn_sleep_for_timestamps() */
2288       *merge_b->use_sleep = TRUE;
2289     }
2290
2291   SVN_ERR(record_update_add(merge_b, local_abspath, svn_node_file,
2292                             fb->add_is_replace, scratch_pool));
2293
2294   return SVN_NO_ERROR;
2295 }
2296
2297 /* Compare the two sets of properties PROPS1 and PROPS2, ignoring the
2298  * "svn:mergeinfo" property, and noticing only "normal" props. Set *SAME to
2299  * true if the rest of the properties are identical or false if they differ.
2300  */
2301 static svn_error_t *
2302 properties_same_p(svn_boolean_t *same,
2303                   apr_hash_t *props1,
2304                   apr_hash_t *props2,
2305                   apr_pool_t *scratch_pool)
2306 {
2307   apr_array_header_t *prop_changes;
2308   int i, diffs;
2309
2310   /* Examine the properties that differ */
2311   SVN_ERR(svn_prop_diffs(&prop_changes, props1, props2, scratch_pool));
2312   diffs = 0;
2313   for (i = 0; i < prop_changes->nelts; i++)
2314     {
2315       const char *pname = APR_ARRAY_IDX(prop_changes, i, svn_prop_t).name;
2316
2317       /* Count the properties we're interested in; ignore the rest */
2318       if (svn_wc_is_normal_prop(pname)
2319           && strcmp(pname, SVN_PROP_MERGEINFO) != 0)
2320         diffs++;
2321     }
2322   *same = (diffs == 0);
2323   return SVN_NO_ERROR;
2324 }
2325
2326 /* Compare the file OLDER_ABSPATH (together with its normal properties in
2327  * ORIGINAL_PROPS which may also contain WC props and entry props) with the
2328  * versioned file MINE_ABSPATH (together with its versioned properties).
2329  * Set *SAME to true if they are the same or false if they differ, ignoring
2330  * the "svn:mergeinfo" property, and ignoring differences in keyword
2331  * expansion and end-of-line style. */
2332 static svn_error_t *
2333 files_same_p(svn_boolean_t *same,
2334              const char *older_abspath,
2335              apr_hash_t *original_props,
2336              const char *mine_abspath,
2337              svn_wc_context_t *wc_ctx,
2338              apr_pool_t *scratch_pool)
2339 {
2340   apr_hash_t *working_props;
2341
2342   SVN_ERR(svn_wc_prop_list2(&working_props, wc_ctx, mine_abspath,
2343                             scratch_pool, scratch_pool));
2344
2345   /* Compare the properties */
2346   SVN_ERR(properties_same_p(same, original_props, working_props,
2347                             scratch_pool));
2348   if (*same)
2349     {
2350       svn_stream_t *mine_stream;
2351       svn_stream_t *older_stream;
2352       svn_string_t *special = svn_hash_gets(working_props, SVN_PROP_SPECIAL);
2353       svn_string_t *eol_style = svn_hash_gets(working_props, SVN_PROP_EOL_STYLE);
2354       svn_string_t *keywords = svn_hash_gets(working_props, SVN_PROP_KEYWORDS);
2355
2356       /* Compare the file content, translating 'mine' to 'normal' form. */
2357       if (special != NULL)
2358         SVN_ERR(svn_subst_read_specialfile(&mine_stream, mine_abspath,
2359                                            scratch_pool, scratch_pool));
2360       else
2361         SVN_ERR(svn_stream_open_readonly(&mine_stream, mine_abspath,
2362                                          scratch_pool, scratch_pool));
2363
2364       if (!special && (eol_style || keywords))
2365         {
2366           apr_hash_t *kw = NULL;
2367           const char *eol = NULL;
2368           svn_subst_eol_style_t style;
2369
2370           /* We used to use svn_client__get_normalized_stream() here, but
2371              that doesn't work in 100% of the cases because it doesn't
2372              convert EOLs to the repository form; just to '\n'.
2373            */
2374
2375           if (eol_style)
2376             {
2377               svn_subst_eol_style_from_value(&style, &eol, eol_style->data);
2378
2379               if (style == svn_subst_eol_style_native)
2380                 eol = SVN_SUBST_NATIVE_EOL_STR;
2381               else if (style != svn_subst_eol_style_fixed
2382                        && style != svn_subst_eol_style_none)
2383                 return svn_error_create(SVN_ERR_IO_UNKNOWN_EOL, NULL, NULL);
2384             }
2385
2386           if (keywords)
2387             SVN_ERR(svn_subst_build_keywords3(&kw, keywords->data, "", "",
2388                                               "", 0, "", scratch_pool));
2389
2390           mine_stream = svn_subst_stream_translated(
2391             mine_stream, eol, FALSE, kw, FALSE, scratch_pool);
2392         }
2393
2394       SVN_ERR(svn_stream_open_readonly(&older_stream, older_abspath,
2395                                        scratch_pool, scratch_pool));
2396
2397       SVN_ERR(svn_stream_contents_same2(same, mine_stream, older_stream,
2398                                         scratch_pool));
2399
2400     }
2401
2402   return SVN_NO_ERROR;
2403 }
2404
2405 /* An svn_diff_tree_processor_t function.
2406  *
2407  * Called after merge_file_opened() when a node does exist in LEFT_SOURCE, but
2408  * no longer exists (or is replaced) in RIGHT_SOURCE.
2409  *
2410  * When a node is replaced instead of just added a separate opened+added will
2411  * be invoked after the current open+deleted.
2412  */
2413 static svn_error_t *
2414 merge_file_deleted(const char *relpath,
2415                    const svn_diff_source_t *left_source,
2416                    const char *left_file,
2417                    /*const*/ apr_hash_t *left_props,
2418                    void *file_baton,
2419                    const struct svn_diff_tree_processor_t *processor,
2420                    apr_pool_t *scratch_pool)
2421 {
2422   merge_cmd_baton_t *merge_b = processor->baton;
2423   struct merge_file_baton_t *fb = file_baton;
2424   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
2425                                               relpath, scratch_pool);
2426   svn_boolean_t same;
2427
2428   SVN_ERR(mark_file_edited(merge_b, fb, local_abspath, scratch_pool));
2429
2430   if (fb->shadowed)
2431     {
2432       if (fb->tree_conflict_reason == CONFLICT_REASON_NONE)
2433         {
2434           /* We haven't notified for this node yet: report a skip */
2435           SVN_ERR(record_skip(merge_b, local_abspath, svn_node_file,
2436                               svn_wc_notify_update_shadowed_delete,
2437                               fb->skip_reason, fb->parent_baton,
2438                               scratch_pool));
2439         }
2440
2441       return SVN_NO_ERROR;
2442     }
2443
2444   /* Easy out: We are only applying mergeinfo differences. */
2445   if (merge_b->record_only)
2446     {
2447       return SVN_NO_ERROR;
2448     }
2449
2450   /* If the files are identical, attempt deletion */
2451   if (merge_b->force_delete)
2452     same = TRUE;
2453   else
2454     SVN_ERR(files_same_p(&same, left_file, left_props,
2455                          local_abspath, merge_b->ctx->wc_ctx,
2456                          scratch_pool));
2457
2458   if (fb->parent_baton
2459       && fb->parent_baton->delete_state)
2460     {
2461       if (same)
2462         {
2463           /* Note that we checked this file */
2464           store_path(fb->parent_baton->delete_state->compared_abspaths,
2465                      local_abspath);
2466         }
2467       else
2468         {
2469           /* We found some modification. Parent should raise a tree conflict */
2470           fb->parent_baton->delete_state->found_edit = TRUE;
2471         }
2472
2473       return SVN_NO_ERROR;
2474     }
2475   else if (same)
2476     {
2477       if (!merge_b->dry_run)
2478         SVN_ERR(svn_wc_delete4(merge_b->ctx->wc_ctx, local_abspath,
2479                                FALSE /* keep_local */, FALSE /* unversioned */,
2480                                merge_b->ctx->cancel_func,
2481                                merge_b->ctx->cancel_baton,
2482                                NULL, NULL /* no notify */,
2483                                scratch_pool));
2484
2485       /* Record that we might have deleted mergeinfo */
2486       alloc_and_store_path(&merge_b->paths_with_deleted_mergeinfo,
2487                            local_abspath, merge_b->pool);
2488
2489       /* And notify the deletion */
2490       SVN_ERR(record_update_delete(merge_b, fb->parent_baton, local_abspath,
2491                                    svn_node_file, scratch_pool));
2492     }
2493   else
2494     {
2495       /* The files differ, so raise a conflict instead of deleting */
2496
2497       /* This is use case 5 described in the paper attached to issue
2498        * #2282.  See also notes/tree-conflicts/detection.txt
2499        */
2500       SVN_ERR(record_tree_conflict(merge_b, local_abspath, fb->parent_baton,
2501                                    svn_node_file,
2502                                    svn_node_file,
2503                                    svn_node_none,
2504                                    svn_wc_conflict_action_delete,
2505                                    svn_wc_conflict_reason_edited,
2506                                    NULL, TRUE,
2507                                    scratch_pool));
2508     }
2509
2510   return SVN_NO_ERROR;
2511 }
2512
2513 /* An svn_diff_tree_processor_t function.
2514
2515    Called before either merge_dir_changed(), merge_dir_added(),
2516    merge_dir_deleted() or merge_dir_closed(), unless it sets *SKIP to TRUE.
2517
2518    After this call and before the close call, all descendants will receive
2519    their changes, unless *SKIP_CHILDREN is set to TRUE.
2520
2521    When *SKIP is TRUE, the diff driver avoids work on getting the details
2522    for the closing callbacks.
2523
2524    The SKIP and SKIP_DESCENDANTS work independently.
2525  */
2526 static svn_error_t *
2527 merge_dir_opened(void **new_dir_baton,
2528                  svn_boolean_t *skip,
2529                  svn_boolean_t *skip_children,
2530                  const char *relpath,
2531                  const svn_diff_source_t *left_source,
2532                  const svn_diff_source_t *right_source,
2533                  const svn_diff_source_t *copyfrom_source,
2534                  void *parent_dir_baton,
2535                  const struct svn_diff_tree_processor_t *processor,
2536                  apr_pool_t *result_pool,
2537                  apr_pool_t *scratch_pool)
2538 {
2539   merge_cmd_baton_t *merge_b = processor->baton;
2540   struct merge_dir_baton_t *db;
2541   struct merge_dir_baton_t *pdb = parent_dir_baton;
2542
2543   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
2544                                               relpath, scratch_pool);
2545
2546   db = apr_pcalloc(result_pool, sizeof(*db));
2547   db->pool = result_pool;
2548   db->tree_conflict_reason = CONFLICT_REASON_NONE;
2549   db->tree_conflict_action = svn_wc_conflict_action_edit;
2550   db->skip_reason = svn_wc_notify_state_unknown;
2551
2552   *new_dir_baton = db;
2553
2554   if (left_source)
2555     db->tree_conflict_merge_left_node_kind = svn_node_dir;
2556   else
2557     db->tree_conflict_merge_left_node_kind = svn_node_none;
2558
2559   if (right_source)
2560     db->tree_conflict_merge_right_node_kind = svn_node_dir;
2561   else
2562     db->tree_conflict_merge_right_node_kind = svn_node_none;
2563
2564   if (pdb)
2565     {
2566       db->parent_baton = pdb;
2567       db->shadowed = pdb->shadowed;
2568       db->skip_reason = pdb->skip_reason;
2569     }
2570
2571   if (db->shadowed)
2572     {
2573       /* An ancestor is tree conflicted. Nothing to do here. */
2574       if (! left_source)
2575         db->added = TRUE;
2576     }
2577   else if (left_source != NULL)
2578     {
2579       /* Node is expected to be a directory. */
2580       svn_boolean_t is_deleted;
2581       svn_boolean_t excluded;
2582       svn_depth_t parent_depth;
2583
2584       if (! right_source)
2585           db->tree_conflict_action = svn_wc_conflict_action_delete;
2586
2587       /* Check for an obstructed or missing node on disk. */
2588       {
2589         svn_wc_notify_state_t obstr_state;
2590         SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, &excluded,
2591                                           &db->tree_conflict_local_node_kind,
2592                                           &parent_depth, merge_b,
2593                                           local_abspath, scratch_pool));
2594
2595         if (obstr_state != svn_wc_notify_state_inapplicable)
2596           {
2597             db->shadowed = TRUE;
2598
2599             if (obstr_state == svn_wc_notify_state_obstructed)
2600               {
2601                 svn_boolean_t is_wcroot;
2602
2603                 SVN_ERR(svn_wc_check_root(&is_wcroot, NULL, NULL,
2604                                         merge_b->ctx->wc_ctx,
2605                                         local_abspath, scratch_pool));
2606
2607                 if (is_wcroot)
2608                   {
2609                     db->tree_conflict_reason = CONFLICT_REASON_SKIP_WC;
2610                     return SVN_NO_ERROR;
2611                   }
2612               }
2613
2614             db->tree_conflict_reason = CONFLICT_REASON_SKIP;
2615             db->skip_reason = obstr_state;
2616
2617             if (! right_source)
2618               {
2619                 *skip = *skip_children = TRUE;
2620                 SVN_ERR(mark_dir_edited(merge_b, db, local_abspath,
2621                                         scratch_pool));
2622               }
2623
2624             return SVN_NO_ERROR;
2625           }
2626
2627         if (is_deleted)
2628           db->tree_conflict_local_node_kind = svn_node_none;
2629       }
2630
2631       if (db->tree_conflict_local_node_kind == svn_node_none)
2632         {
2633           db->shadowed = TRUE;
2634
2635           /* If this is not the merge target and the parent is too shallow to
2636              contain this directory, and the directory is not presen
2637              via exclusion or depth filtering, skip it instead of recording
2638              a tree conflict.
2639
2640              Non-inheritable mergeinfo will be recorded, allowing
2641              future merges into non-shallow working copies to merge
2642              changes we missed this time around. */
2643           if (pdb && (excluded
2644                       || (parent_depth != svn_depth_unknown &&
2645                           parent_depth < svn_depth_immediates)))
2646             {
2647               db->shadowed = TRUE;
2648
2649               db->tree_conflict_reason = CONFLICT_REASON_SKIP;
2650               db->skip_reason = svn_wc_notify_state_missing;
2651
2652               return SVN_NO_ERROR;
2653             }
2654
2655           if (is_deleted)
2656             db->tree_conflict_reason = svn_wc_conflict_reason_deleted;
2657           else
2658             db->tree_conflict_reason = svn_wc_conflict_reason_missing;
2659
2660           /* ### To avoid breaking tests */
2661           *skip = TRUE;
2662           *skip_children = TRUE;
2663           SVN_ERR(mark_dir_edited(merge_b, db, local_abspath, scratch_pool));
2664           return SVN_NO_ERROR;
2665           /* ### /avoid breaking tests */
2666         }
2667       else if (db->tree_conflict_local_node_kind != svn_node_dir)
2668         {
2669           svn_boolean_t added;
2670
2671           db->shadowed = TRUE;
2672           SVN_ERR(svn_wc__node_is_added(&added, merge_b->ctx->wc_ctx,
2673                                         local_abspath, scratch_pool));
2674
2675           db->tree_conflict_reason = added ? svn_wc_conflict_reason_added
2676                                            : svn_wc_conflict_reason_obstructed;
2677
2678           /* ### To avoid breaking tests */
2679           *skip = TRUE;
2680           *skip_children = TRUE;
2681           SVN_ERR(mark_dir_edited(merge_b, db, local_abspath, scratch_pool));
2682           return SVN_NO_ERROR;
2683           /* ### /avoid breaking tests */
2684         }
2685
2686       if (! right_source)
2687         {
2688           /* We want to delete the directory */
2689           /* Mark PB edited now? */
2690           db->tree_conflict_action = svn_wc_conflict_action_delete;
2691           SVN_ERR(mark_dir_edited(merge_b, db, local_abspath, scratch_pool));
2692
2693           if (db->shadowed)
2694             {
2695               *skip_children = TRUE;
2696               return SVN_NO_ERROR; /* Already set a tree conflict */
2697             }
2698
2699           db->delete_state = (pdb != NULL) ? pdb->delete_state : NULL;
2700
2701           if (db->delete_state && db->delete_state->found_edit)
2702             {
2703               /* A sibling found a conflict. Done. */
2704               *skip = TRUE;
2705               *skip_children = TRUE;
2706             }
2707           else if (merge_b->force_delete)
2708             {
2709               /* No comparison necessary */
2710               *skip_children = TRUE;
2711             }
2712           else if (! db->delete_state)
2713             {
2714               /* Start descendant comparison */
2715               db->delete_state = apr_pcalloc(db->pool,
2716                                              sizeof(*db->delete_state));
2717
2718               db->delete_state->del_root = db;
2719               db->delete_state->compared_abspaths = apr_hash_make(db->pool);
2720             }
2721         }
2722     }
2723   else
2724     {
2725       const svn_wc_conflict_description2_t *old_tc = NULL;
2726
2727       /* The node doesn't exist pre-merge: We have an addition */
2728       db->added = TRUE;
2729       db->tree_conflict_action = svn_wc_conflict_action_add;
2730
2731       if (pdb && pdb->pending_deletes
2732           && svn_hash_gets(pdb->pending_deletes, local_abspath))
2733         {
2734           db->add_is_replace = TRUE;
2735           db->tree_conflict_action = svn_wc_conflict_action_replace;
2736
2737           svn_hash_sets(pdb->pending_deletes, local_abspath, NULL);
2738         }
2739
2740       if (pdb
2741           && pdb->new_tree_conflicts
2742           && (old_tc = svn_hash_gets(pdb->new_tree_conflicts, local_abspath)))
2743         {
2744           db->tree_conflict_action = svn_wc_conflict_action_replace;
2745           db->tree_conflict_reason = old_tc->reason;
2746
2747           if (old_tc->reason == svn_wc_conflict_reason_deleted
2748              || old_tc->reason == svn_wc_conflict_reason_moved_away)
2749             {
2750               /* Issue #3806: Incoming replacements on local deletes produce
2751                  inconsistent result.
2752
2753                  In this specific case we can continue applying the add part
2754                  of the replacement. */
2755             }
2756           else
2757             {
2758               *skip = TRUE;
2759               *skip_children = TRUE;
2760
2761               /* Update the tree conflict to store that this is a replace */
2762               SVN_ERR(record_tree_conflict(merge_b, local_abspath, pdb,
2763                                            old_tc->node_kind,
2764                                            old_tc->src_left_version->node_kind,
2765                                            svn_node_dir,
2766                                            db->tree_conflict_action,
2767                                            db->tree_conflict_reason,
2768                                            old_tc, FALSE,
2769                                            scratch_pool));
2770
2771               return SVN_NO_ERROR;
2772             }
2773         }
2774
2775       if (! (merge_b->dry_run
2776              && ((pdb && pdb->added) || db->add_is_replace)))
2777         {
2778           svn_wc_notify_state_t obstr_state;
2779           svn_boolean_t is_deleted;
2780
2781           SVN_ERR(perform_obstruction_check(&obstr_state, &is_deleted, NULL,
2782                                             &db->tree_conflict_local_node_kind,
2783                                             NULL, merge_b, local_abspath,
2784                                             scratch_pool));
2785
2786           /* In this case of adding a directory, we have an exception to the
2787            * usual "skip if it's inconsistent" rule. If the directory exists
2788            * on disk unexpectedly, we simply make it versioned, because we can
2789            * do so without risk of destroying data. Only skip if it is
2790            * versioned but unexpectedly missing from disk, or is unversioned
2791            * but obstructed by a node of the wrong kind. */
2792           if (obstr_state == svn_wc_notify_state_obstructed
2793               && (is_deleted ||
2794                   db->tree_conflict_local_node_kind == svn_node_none))
2795             {
2796               svn_node_kind_t disk_kind;
2797
2798               SVN_ERR(svn_io_check_path(local_abspath, &disk_kind,
2799                                         scratch_pool));
2800
2801               if (disk_kind == svn_node_dir)
2802                 {
2803                   obstr_state = svn_wc_notify_state_inapplicable;
2804                   db->add_existing = TRUE; /* Take over existing directory */
2805                 }
2806             }
2807
2808           if (obstr_state != svn_wc_notify_state_inapplicable)
2809             {
2810               /* Skip the obstruction */
2811               db->shadowed = TRUE;
2812               db->tree_conflict_reason = CONFLICT_REASON_SKIP;
2813               db->skip_reason = obstr_state;
2814             }
2815           else if (db->tree_conflict_local_node_kind != svn_node_none
2816                    && !is_deleted)
2817             {
2818               /* Set a tree conflict */
2819               svn_boolean_t added;
2820               db->shadowed = TRUE;
2821
2822               SVN_ERR(svn_wc__node_is_added(&added, merge_b->ctx->wc_ctx,
2823                                             local_abspath, scratch_pool));
2824
2825               db->tree_conflict_reason = added ? svn_wc_conflict_reason_added
2826                                                : svn_wc_conflict_reason_obstructed;
2827             }
2828         }
2829
2830       /* Handle pending conflicts */
2831       SVN_ERR(mark_dir_edited(merge_b, db, local_abspath, scratch_pool));
2832
2833       if (db->shadowed)
2834         {
2835           /* Notified and done. Skip children? */
2836         }
2837       else if (merge_b->record_only)
2838         {
2839           /* Ok, we are done for this node and its descendants */
2840           *skip = TRUE;
2841           *skip_children = TRUE;
2842         }
2843       else if (! merge_b->dry_run)
2844         {
2845           /* Create the directory on disk, to allow descendants to be added */
2846           if (! db->add_existing)
2847             SVN_ERR(svn_io_dir_make(local_abspath, APR_OS_DEFAULT,
2848                                     scratch_pool));
2849
2850           if (old_tc)
2851             {
2852               /* svn_wc_add4 and svn_wc_add_from_disk3 can't add a node
2853                  over an existing tree conflict */
2854
2855               /* ### These functions should take some tree conflict argument
2856                      and allow overwriting the tc when one is passed */
2857
2858               SVN_ERR(svn_wc__del_tree_conflict(merge_b->ctx->wc_ctx,
2859                                                 local_abspath,
2860                                                 scratch_pool));
2861             }
2862
2863           if (merge_b->same_repos)
2864             {
2865               const char *original_url;
2866
2867               original_url = svn_path_url_add_component2(
2868                                         merge_b->merge_source.loc2->url,
2869                                         relpath, scratch_pool);
2870
2871               /* Limitation (aka HACK):
2872                  We create a newly added directory with an original URL and
2873                  revision as that in the repository, but without its properties
2874                  and children.
2875
2876                  When the merge is cancelled before the final dir_added(), the
2877                  copy won't really represent the in-repository state of the node.
2878                */
2879               SVN_ERR(svn_wc_add4(merge_b->ctx->wc_ctx, local_abspath,
2880                                   svn_depth_infinity,
2881                                   original_url,
2882                                   right_source->revision,
2883                                   merge_b->ctx->cancel_func,
2884                                   merge_b->ctx->cancel_baton,
2885                                   NULL, NULL /* no notify! */,
2886                                   scratch_pool));
2887             }
2888           else
2889             {
2890               SVN_ERR(svn_wc_add_from_disk3(merge_b->ctx->wc_ctx, local_abspath,
2891                                             apr_hash_make(scratch_pool),
2892                                             FALSE /* skip checks */,
2893                                             NULL, NULL /* no notify! */,
2894                                             scratch_pool));
2895             }
2896
2897           if (old_tc != NULL)
2898             {
2899               /* ### Should be atomic with svn_wc_add(4|_from_disk2)() */
2900               SVN_ERR(record_tree_conflict(merge_b, local_abspath, pdb,
2901                                            old_tc->node_kind,
2902                                            svn_node_none,
2903                                            svn_node_dir,
2904                                            db->tree_conflict_action,
2905                                            db->tree_conflict_reason,
2906                                            old_tc, FALSE,
2907                                            scratch_pool));
2908             }
2909         }
2910
2911       if (! db->shadowed && !merge_b->record_only)
2912         SVN_ERR(record_update_add(merge_b, local_abspath, svn_node_dir,
2913                                   db->add_is_replace, scratch_pool));
2914     }
2915   return SVN_NO_ERROR;
2916 }
2917
2918 /* An svn_diff_tree_processor_t function.
2919  *
2920  * Called after merge_dir_opened() when a node exists in both the left and
2921  * right source, but has its properties changed inbetween.
2922  *
2923  * After the merge_dir_opened() but before the call to this merge_dir_changed()
2924  * function all descendants will have been updated.
2925  */
2926 static svn_error_t *
2927 merge_dir_changed(const char *relpath,
2928                   const svn_diff_source_t *left_source,
2929                   const svn_diff_source_t *right_source,
2930                   /*const*/ apr_hash_t *left_props,
2931                   /*const*/ apr_hash_t *right_props,
2932                   const apr_array_header_t *prop_changes,
2933                   void *dir_baton,
2934                   const struct svn_diff_tree_processor_t *processor,
2935                   apr_pool_t *scratch_pool)
2936 {
2937   merge_cmd_baton_t *merge_b = processor->baton;
2938   struct merge_dir_baton_t *db = dir_baton;
2939   const apr_array_header_t *props;
2940   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
2941                                               relpath, scratch_pool);
2942
2943   SVN_ERR(handle_pending_notifications(merge_b, db, scratch_pool));
2944
2945   SVN_ERR(mark_dir_edited(merge_b, db, local_abspath, scratch_pool));
2946
2947   if (db->shadowed)
2948     {
2949       if (db->tree_conflict_reason == CONFLICT_REASON_NONE)
2950         {
2951           /* We haven't notified for this node yet: report a skip */
2952           SVN_ERR(record_skip(merge_b, local_abspath, svn_node_dir,
2953                               svn_wc_notify_update_shadowed_update,
2954                               db->skip_reason, db->parent_baton,
2955                               scratch_pool));
2956         }
2957
2958       return SVN_NO_ERROR;
2959     }
2960
2961   SVN_ERR(prepare_merge_props_changed(&props, local_abspath, prop_changes,
2962                                       merge_b, scratch_pool, scratch_pool));
2963
2964   if (props->nelts)
2965     {
2966       const svn_wc_conflict_version_t *left;
2967       const svn_wc_conflict_version_t *right;
2968       svn_client_ctx_t *ctx = merge_b->ctx;
2969       svn_wc_notify_state_t prop_state;
2970
2971       SVN_ERR(make_conflict_versions(&left, &right, local_abspath,
2972                                      svn_node_dir, svn_node_dir,
2973                                      &merge_b->merge_source,
2974                                      merge_b->target,
2975                                      scratch_pool, scratch_pool));
2976
2977       SVN_ERR(svn_wc_merge_props3(&prop_state, ctx->wc_ctx, local_abspath,
2978                                   left, right,
2979                                   left_props, props,
2980                                   merge_b->dry_run,
2981                                   NULL, NULL,
2982                                   ctx->cancel_func, ctx->cancel_baton,
2983                                   scratch_pool));
2984
2985       if (prop_state == svn_wc_notify_state_conflicted)
2986         {
2987           alloc_and_store_path(&merge_b->conflicted_paths, local_abspath,
2988                                merge_b->pool);
2989         }
2990
2991       if (prop_state == svn_wc_notify_state_conflicted
2992           || prop_state == svn_wc_notify_state_merged
2993           || prop_state == svn_wc_notify_state_changed)
2994         {
2995           SVN_ERR(record_update_update(merge_b, local_abspath, svn_node_file,
2996                                        svn_wc_notify_state_inapplicable,
2997                                        prop_state, scratch_pool));
2998         }
2999     }
3000
3001   return SVN_NO_ERROR;
3002 }
3003
3004
3005 /* An svn_diff_tree_processor_t function.
3006  *
3007  * Called after merge_dir_opened() when a node doesn't exist in LEFT_SOURCE,
3008  * but does in RIGHT_SOURCE. After the merge_dir_opened() but before the call
3009  * to this merge_dir_added() function all descendants will have been added.
3010  *
3011  * When a node is replaced instead of just added a separate opened+deleted will
3012  * be invoked before the current open+added.
3013  */
3014 static svn_error_t *
3015 merge_dir_added(const char *relpath,
3016                 const svn_diff_source_t *copyfrom_source,
3017                 const svn_diff_source_t *right_source,
3018                 /*const*/ apr_hash_t *copyfrom_props,
3019                 /*const*/ apr_hash_t *right_props,
3020                 void *dir_baton,
3021                 const struct svn_diff_tree_processor_t *processor,
3022                 apr_pool_t *scratch_pool)
3023 {
3024   merge_cmd_baton_t *merge_b = processor->baton;
3025   struct merge_dir_baton_t *db = dir_baton;
3026   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
3027                                               relpath, scratch_pool);
3028
3029   /* For consistency; usually a no-op from _dir_added() */
3030   SVN_ERR(handle_pending_notifications(merge_b, db, scratch_pool));
3031   SVN_ERR(mark_dir_edited(merge_b, db, local_abspath, scratch_pool));
3032
3033   if (db->shadowed)
3034     {
3035       if (db->tree_conflict_reason == CONFLICT_REASON_NONE)
3036         {
3037           /* We haven't notified for this node yet: report a skip */
3038           SVN_ERR(record_skip(merge_b, local_abspath, svn_node_dir,
3039                               svn_wc_notify_update_shadowed_add,
3040                               db->skip_reason, db->parent_baton,
3041                               scratch_pool));
3042         }
3043
3044       return SVN_NO_ERROR;
3045     }
3046
3047   SVN_ERR_ASSERT(
3048                  db->edited                  /* Marked edited from merge_open_dir() */
3049                  && ! merge_b->record_only /* Skip details from merge_open_dir() */
3050                  );
3051
3052   if ((merge_b->merge_source.ancestral || merge_b->reintegrate_merge)
3053       && ( !db->parent_baton || !db->parent_baton->added))
3054     {
3055       /* Store the roots of added subtrees */
3056       store_path(merge_b->added_abspaths, local_abspath);
3057     }
3058
3059   if (merge_b->same_repos)
3060     {
3061       /* When the directory was added in merge_dir_added() we didn't update its
3062          pristine properties. Instead we receive the property changes later and
3063          apply them in this function.
3064
3065          If we would apply them as changes (such as before fixing issue #3405),
3066          we would see the unmodified properties as local changes, and the
3067          pristine properties would be out of sync with what the repository
3068          expects for this directory.
3069
3070          Instead of doing that we now simply set the properties as the pristine
3071          properties via a private libsvn_wc api.
3072       */
3073
3074       const char *copyfrom_url;
3075       svn_revnum_t copyfrom_rev;
3076       const char *parent_abspath;
3077       const char *child;
3078
3079       /* Creating a hash containing regular and entry props */
3080       apr_hash_t *new_pristine_props = right_props;
3081
3082       parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
3083       child = svn_dirent_is_child(merge_b->target->abspath, local_abspath, NULL);
3084       SVN_ERR_ASSERT(child != NULL);
3085
3086       copyfrom_url = svn_path_url_add_component2(merge_b->merge_source.loc2->url,
3087                                                  child, scratch_pool);
3088       copyfrom_rev = right_source->revision;
3089
3090       SVN_ERR(check_repos_match(merge_b->target, parent_abspath, copyfrom_url,
3091                                 scratch_pool));
3092
3093       if (!merge_b->dry_run)
3094         {
3095           SVN_ERR(svn_wc__complete_directory_add(merge_b->ctx->wc_ctx,
3096                                                 local_abspath,
3097                                                 new_pristine_props,
3098                                                 copyfrom_url, copyfrom_rev,
3099                                                 scratch_pool));
3100         }
3101
3102       if (svn_hash_gets(new_pristine_props, SVN_PROP_MERGEINFO))
3103         {
3104           alloc_and_store_path(&merge_b->paths_with_new_mergeinfo,
3105                                local_abspath, merge_b->pool);
3106         }
3107     }
3108   else
3109     {
3110       apr_array_header_t *regular_props;
3111       apr_hash_t *new_props;
3112       svn_wc_notify_state_t prop_state;
3113
3114       SVN_ERR(svn_categorize_props(svn_prop_hash_to_array(right_props,
3115                                                           scratch_pool),
3116                                    NULL, NULL, &regular_props, scratch_pool));
3117
3118       new_props = svn_prop_array_to_hash(regular_props, scratch_pool);
3119
3120       svn_hash_sets(new_props, SVN_PROP_MERGEINFO, NULL);
3121
3122       /* ### What is the easiest way to set new_props on LOCAL_ABSPATH?
3123
3124          ### This doesn't need a merge as we just added the node
3125          ### (or installed a tree conflict and skipped this node)*/
3126
3127       SVN_ERR(svn_wc_merge_props3(&prop_state, merge_b->ctx->wc_ctx,
3128                                   local_abspath,
3129                                   NULL, NULL,
3130                                   apr_hash_make(scratch_pool),
3131                                   svn_prop_hash_to_array(new_props,
3132                                                          scratch_pool),
3133                                   merge_b->dry_run,
3134                                   NULL, NULL,
3135                                   merge_b->ctx->cancel_func,
3136                                   merge_b->ctx->cancel_baton,
3137                                   scratch_pool));
3138       if (prop_state == svn_wc_notify_state_conflicted)
3139         {
3140           alloc_and_store_path(&merge_b->conflicted_paths, local_abspath,
3141                                merge_b->pool);
3142         }
3143     }
3144
3145   return SVN_NO_ERROR;
3146 }
3147
3148 /* Helper for merge_dir_deleted. Implement svn_wc_status_func4_t */
3149 static svn_error_t *
3150 verify_touched_by_del_check(void *baton,
3151                             const char *local_abspath,
3152                             const svn_wc_status3_t *status,
3153                             apr_pool_t *scratch_pool)
3154 {
3155   struct dir_delete_baton_t *delb = baton;
3156
3157   if (svn_hash_gets(delb->compared_abspaths, local_abspath))
3158     return SVN_NO_ERROR;
3159
3160   switch (status->node_status)
3161     {
3162       case svn_wc_status_deleted:
3163       case svn_wc_status_ignored:
3164       case svn_wc_status_none:
3165         return SVN_NO_ERROR;
3166
3167       default:
3168         delb->found_edit = TRUE;
3169         return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
3170     }
3171 }
3172
3173 /* An svn_diff_tree_processor_t function.
3174  *
3175  * Called after merge_dir_opened() when a node existed only in the left source.
3176  *
3177  * After the merge_dir_opened() but before the call to this merge_dir_deleted()
3178  * function all descendants that existed in left_source will have been deleted.
3179  *
3180  * If this node is replaced, an _opened() followed by a matching _add() will
3181  * be invoked after this function.
3182  */
3183 static svn_error_t *
3184 merge_dir_deleted(const char *relpath,
3185                   const svn_diff_source_t *left_source,
3186                   /*const*/ apr_hash_t *left_props,
3187                   void *dir_baton,
3188                   const struct svn_diff_tree_processor_t *processor,
3189                   apr_pool_t *scratch_pool)
3190 {
3191   merge_cmd_baton_t *merge_b = processor->baton;
3192   struct merge_dir_baton_t *db = dir_baton;
3193   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
3194                                               relpath, scratch_pool);
3195   svn_boolean_t same;
3196   apr_hash_t *working_props;
3197
3198   SVN_ERR(handle_pending_notifications(merge_b, db, scratch_pool));
3199   SVN_ERR(mark_dir_edited(merge_b, db, local_abspath, scratch_pool));
3200
3201   if (db->shadowed)
3202     {
3203       if (db->tree_conflict_reason == CONFLICT_REASON_NONE)
3204         {
3205           /* We haven't notified for this node yet: report a skip */
3206           SVN_ERR(record_skip(merge_b, local_abspath, svn_node_dir,
3207                               svn_wc_notify_update_shadowed_delete,
3208                               db->skip_reason, db->parent_baton,
3209                               scratch_pool));
3210         }
3211
3212       return SVN_NO_ERROR;
3213     }
3214
3215   /* Easy out: We are only applying mergeinfo differences. */
3216   if (merge_b->record_only)
3217     {
3218       return SVN_NO_ERROR;
3219     }
3220
3221   SVN_ERR(svn_wc_prop_list2(&working_props,
3222                             merge_b->ctx->wc_ctx, local_abspath,
3223                             scratch_pool, scratch_pool));
3224
3225   if (merge_b->force_delete)
3226     {
3227       /* In this legacy mode we just assume that a directory delete
3228          matches any directory. db->delete_state is NULL */
3229       same = TRUE;
3230     }
3231   else
3232     {
3233       struct dir_delete_baton_t *delb;
3234
3235       /* Compare the properties */
3236       SVN_ERR(properties_same_p(&same, left_props, working_props,
3237                                 scratch_pool));
3238       delb = db->delete_state;
3239       assert(delb != NULL);
3240
3241       if (! same)
3242         {
3243           delb->found_edit = TRUE;
3244         }
3245       else
3246         {
3247           store_path(delb->compared_abspaths, local_abspath);
3248         }
3249
3250       if (delb->del_root != db)
3251         return SVN_NO_ERROR;
3252
3253       if (delb->found_edit)
3254         same = FALSE;
3255       else
3256         {
3257           apr_array_header_t *ignores;
3258           svn_error_t *err;
3259           same = TRUE;
3260
3261           SVN_ERR(svn_wc_get_default_ignores(&ignores, merge_b->ctx->config,
3262                                              scratch_pool));
3263
3264           /* None of the descendants was modified, but maybe there are
3265              descendants we haven't walked?
3266
3267              Note that we aren't interested in changes, as we already verified
3268              changes in the paths touched by the merge. And the existence of
3269              other paths is enough to mark the directory edited */
3270           err = svn_wc_walk_status(merge_b->ctx->wc_ctx, local_abspath,
3271                                    svn_depth_infinity, TRUE /* get-all */,
3272                                    FALSE /* no-ignore */,
3273                                    TRUE /* ignore-text-mods */, ignores,
3274                                    verify_touched_by_del_check, delb,
3275                                    merge_b->ctx->cancel_func,
3276                                    merge_b->ctx->cancel_baton,
3277                                    scratch_pool);
3278
3279           if (err)
3280             {
3281               if (err->apr_err != SVN_ERR_CEASE_INVOCATION)
3282                 return svn_error_trace(err);
3283
3284               svn_error_clear(err);
3285             }
3286
3287           same = ! delb->found_edit;
3288         }
3289     }
3290
3291   if (same && !merge_b->dry_run)
3292     {
3293       svn_error_t *err;
3294
3295       err = svn_wc_delete4(merge_b->ctx->wc_ctx, local_abspath,
3296                            FALSE /* keep_local */, FALSE /* unversioned */,
3297                            merge_b->ctx->cancel_func,
3298                            merge_b->ctx->cancel_baton,
3299                            NULL, NULL /* no notify */,
3300                            scratch_pool);
3301
3302       if (err)
3303         {
3304           if (err->apr_err != SVN_ERR_WC_LEFT_LOCAL_MOD)
3305             return svn_error_trace(err);
3306
3307           svn_error_clear(err);
3308           same = FALSE;
3309         }
3310     }
3311
3312   if (! same)
3313     {
3314       /* If the attempt to delete an existing directory failed,
3315        * the directory has local modifications (e.g. locally added
3316        * files, or property changes). Flag a tree conflict. */
3317
3318       /* This handles use case 5 described in the paper attached to issue
3319        * #2282.  See also notes/tree-conflicts/detection.txt
3320        */
3321       SVN_ERR(record_tree_conflict(merge_b, local_abspath, db->parent_baton,
3322                                    svn_node_dir,
3323                                    svn_node_dir,
3324                                    svn_node_none,
3325                                    svn_wc_conflict_action_delete,
3326                                    svn_wc_conflict_reason_edited,
3327                                    NULL, TRUE,
3328                                    scratch_pool));
3329     }
3330   else
3331     {
3332       /* Record that we might have deleted mergeinfo */
3333       if (working_props
3334           && svn_hash_gets(working_props, SVN_PROP_MERGEINFO))
3335         {
3336           alloc_and_store_path(&merge_b->paths_with_deleted_mergeinfo,
3337                                local_abspath, merge_b->pool);
3338         }
3339
3340       SVN_ERR(record_update_delete(merge_b, db->parent_baton, local_abspath,
3341                                    svn_node_dir, scratch_pool));
3342     }
3343
3344   return SVN_NO_ERROR;
3345 }
3346
3347 /* An svn_diff_tree_processor_t function.
3348  *
3349  * Called after merge_dir_opened() when a node itself didn't change between
3350  * the left and right source.
3351  *
3352  * After the merge_dir_opened() but before the call to this merge_dir_closed()
3353  * function all descendants will have been processed.
3354  */
3355 static svn_error_t *
3356 merge_dir_closed(const char *relpath,
3357                  const svn_diff_source_t *left_source,
3358                  const svn_diff_source_t *right_source,
3359                  void *dir_baton,
3360                  const struct svn_diff_tree_processor_t *processor,
3361                  apr_pool_t *scratch_pool)
3362 {
3363   merge_cmd_baton_t *merge_b = processor->baton;
3364   struct merge_dir_baton_t *db = dir_baton;
3365
3366   SVN_ERR(handle_pending_notifications(merge_b, db, scratch_pool));
3367
3368   return SVN_NO_ERROR;
3369 }
3370
3371 /* An svn_diff_tree_processor_t function.
3372
3373    Called when the diff driver wants to report an absent path.
3374
3375    In case of merges this happens when the diff encounters a server-excluded
3376    path.
3377
3378    We register a skipped path, which will make parent mergeinfo non-
3379    inheritable. This ensures that a future merge might see these skipped
3380    changes as eligable for merging.
3381
3382    For legacy reasons we also notify the path as skipped.
3383  */
3384 static svn_error_t *
3385 merge_node_absent(const char *relpath,
3386                   void *dir_baton,
3387                   const svn_diff_tree_processor_t *processor,
3388                   apr_pool_t *scratch_pool)
3389 {
3390   merge_cmd_baton_t *merge_b = processor->baton;
3391   struct merge_dir_baton_t *db = dir_baton;
3392
3393   const char *local_abspath = svn_dirent_join(merge_b->target->abspath,
3394                                               relpath, scratch_pool);
3395
3396   SVN_ERR(record_skip(merge_b, local_abspath, svn_node_unknown,
3397                       svn_wc_notify_skip, svn_wc_notify_state_missing,
3398                       db, scratch_pool));
3399
3400   return SVN_NO_ERROR;
3401 }
3402
3403 /*-----------------------------------------------------------------------*/
3404 \f
3405 /*** Merge Notification ***/
3406
3407
3408 /* Finds a nearest ancestor in CHILDREN_WITH_MERGEINFO for LOCAL_ABSPATH. If
3409    PATH_IS_OWN_ANCESTOR is TRUE then a child in CHILDREN_WITH_MERGEINFO
3410    where child->abspath == PATH is considered PATH's ancestor.  If FALSE,
3411    then child->abspath must be a proper ancestor of PATH.
3412
3413    CHILDREN_WITH_MERGEINFO is expected to be sorted in Depth first
3414    order of path. */
3415 static svn_client__merge_path_t *
3416 find_nearest_ancestor(const apr_array_header_t *children_with_mergeinfo,
3417                       svn_boolean_t path_is_own_ancestor,
3418                       const char *local_abspath)
3419 {
3420   int i;
3421
3422   SVN_ERR_ASSERT_NO_RETURN(children_with_mergeinfo != NULL);
3423
3424   for (i = children_with_mergeinfo->nelts - 1; i >= 0 ; i--)
3425     {
3426       svn_client__merge_path_t *child =
3427         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
3428
3429       if (svn_dirent_is_ancestor(child->abspath, local_abspath)
3430           && (path_is_own_ancestor
3431               || strcmp(child->abspath, local_abspath) != 0))
3432         return child;
3433     }
3434   return NULL;
3435 }
3436
3437 /* Find the highest level path in a merge target (possibly the merge target
3438    itself) to use in a merge notification header.
3439
3440    Return the svn_client__merge_path_t * representing the most distant
3441    ancestor in CHILDREN_WITH_MERGEINFO of LOCAL_ABSPATH where said
3442    ancestor's first remaining ranges element (per the REMAINING_RANGES
3443    member of the ancestor) intersect with the first remaining ranges element
3444    for every intermediate ancestor svn_client__merge_path_t * of
3445    LOCAL_ABSPATH.  If no such ancestor is found return NULL.
3446
3447    If the remaining ranges of the elements in CHILDREN_WITH_MERGEINFO
3448    represent a forward merge, then set *START to the oldest revision found
3449    in any of the intersecting ancestors and *END to the youngest revision
3450    found.  If the remaining ranges of the elements in CHILDREN_WITH_MERGEINFO
3451    represent a reverse merge, then set *START to the youngest revision
3452    found and *END to the oldest revision found.  If no ancestors are found
3453    then set *START and *END to SVN_INVALID_REVNUM.
3454
3455    If PATH_IS_OWN_ANCESTOR is TRUE then a child in CHILDREN_WITH_MERGEINFO
3456    where child->abspath == PATH is considered PATH's ancestor.  If FALSE,
3457    then child->abspath must be a proper ancestor of PATH.
3458
3459    See the CHILDREN_WITH_MERGEINFO ARRAY global comment for more
3460    information. */
3461 static svn_client__merge_path_t *
3462 find_nearest_ancestor_with_intersecting_ranges(
3463   svn_revnum_t *start,
3464   svn_revnum_t *end,
3465   const apr_array_header_t *children_with_mergeinfo,
3466   svn_boolean_t path_is_own_ancestor,
3467   const char *local_abspath)
3468 {
3469   int i;
3470   svn_client__merge_path_t *nearest_ancestor = NULL;
3471
3472   *start = SVN_INVALID_REVNUM;
3473   *end = SVN_INVALID_REVNUM;
3474
3475   SVN_ERR_ASSERT_NO_RETURN(children_with_mergeinfo != NULL);
3476
3477   for (i = children_with_mergeinfo->nelts - 1; i >= 0 ; i--)
3478     {
3479       svn_client__merge_path_t *child =
3480         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
3481
3482       if (svn_dirent_is_ancestor(child->abspath, local_abspath)
3483           && (path_is_own_ancestor
3484               || strcmp(child->abspath, local_abspath) != 0))
3485         {
3486           if (nearest_ancestor == NULL)
3487             {
3488               /* Found an ancestor. */
3489               nearest_ancestor = child;
3490
3491               if (child->remaining_ranges)
3492                 {
3493                   svn_merge_range_t *r1 = APR_ARRAY_IDX(
3494                     child->remaining_ranges, 0, svn_merge_range_t *);
3495                   *start = r1->start;
3496                   *end = r1->end;
3497                 }
3498               else
3499                 {
3500                   /* If CHILD->REMAINING_RANGES is null then LOCAL_ABSPATH
3501                      is inside an absent subtree in the merge target. */
3502                   *start = SVN_INVALID_REVNUM;
3503                   *end = SVN_INVALID_REVNUM;
3504                   break;
3505                 }
3506             }
3507           else
3508             {
3509               /* We'e found another ancestor for LOCAL_ABSPATH.  Do its
3510                  first remaining range intersect with the previously
3511                  found ancestor? */
3512               svn_merge_range_t *r1 =
3513                 APR_ARRAY_IDX(nearest_ancestor->remaining_ranges, 0,
3514                               svn_merge_range_t *);
3515               svn_merge_range_t *r2 =
3516                 APR_ARRAY_IDX(child->remaining_ranges, 0,
3517                               svn_merge_range_t *);
3518
3519               if (r1 && r2)
3520                 {
3521                   svn_merge_range_t range1;
3522                   svn_merge_range_t range2;
3523                   svn_boolean_t reverse_merge = r1->start > r2->end;
3524
3525                   /* Flip endpoints if this is a reverse merge. */
3526                   if (reverse_merge)
3527                     {
3528                       range1.start = r1->end;
3529                       range1.end = r1->start;
3530                       range2.start = r2->end;
3531                       range2.end = r2->start;
3532                     }
3533                   else
3534                     {
3535                       range1.start = r1->start;
3536                       range1.end = r1->end;
3537                       range2.start = r2->start;
3538                       range2.end = r2->end;
3539                     }
3540
3541                   if (range1.start < range2.end && range2.start < range1.end)
3542                     {
3543                       *start = reverse_merge ?
3544                         MAX(r1->start, r2->start) : MIN(r1->start, r2->start);
3545                       *end = reverse_merge ?
3546                         MIN(r1->end, r2->end) : MAX(r1->end, r2->end);
3547                       nearest_ancestor = child;
3548                     }
3549                 }
3550             }
3551         }
3552     }
3553   return nearest_ancestor;
3554 }
3555
3556 /* Notify that we're starting to record mergeinfo for the merge of the
3557  * revision range RANGE into TARGET_ABSPATH.  RANGE should be null if the
3558  * merge sources are not from the same URL.
3559  *
3560  * This calls the client's notification receiver (as found in the client
3561  * context), with a WC abspath.
3562  */
3563 static void
3564 notify_mergeinfo_recording(const char *target_abspath,
3565                            const svn_merge_range_t *range,
3566                            svn_client_ctx_t *ctx,
3567                            apr_pool_t *pool)
3568 {
3569   if (ctx->notify_func2)
3570     {
3571       svn_wc_notify_t *n = svn_wc_create_notify(
3572         target_abspath, svn_wc_notify_merge_record_info_begin, pool);
3573
3574       n->merge_range = range ? svn_merge_range_dup(range, pool) : NULL;
3575       ctx->notify_func2(ctx->notify_baton2, n, pool);
3576     }
3577 }
3578
3579 /* Notify that we're completing the merge into TARGET_ABSPATH.
3580  *
3581  * This calls the client's notification receiver (as found in the client
3582  * context), with a WC abspath.
3583  */
3584 static void
3585 notify_merge_completed(const char *target_abspath,
3586                        svn_client_ctx_t *ctx,
3587                        apr_pool_t *pool)
3588 {
3589   if (ctx->notify_func2)
3590     {
3591       svn_wc_notify_t *n
3592         = svn_wc_create_notify(target_abspath, svn_wc_notify_merge_completed,
3593                                pool);
3594       ctx->notify_func2(ctx->notify_baton2, n, pool);
3595     }
3596 }
3597
3598 /* Is the notification the result of a real operative merge? */
3599 #define IS_OPERATIVE_NOTIFICATION(notify)  \
3600                     (notify->content_state == svn_wc_notify_state_conflicted \
3601                      || notify->content_state == svn_wc_notify_state_merged  \
3602                      || notify->content_state == svn_wc_notify_state_changed \
3603                      || notify->prop_state == svn_wc_notify_state_conflicted \
3604                      || notify->prop_state == svn_wc_notify_state_merged     \
3605                      || notify->prop_state == svn_wc_notify_state_changed    \
3606                      || notify->action == svn_wc_notify_update_add \
3607                      || notify->action == svn_wc_notify_tree_conflict)
3608
3609
3610 /* Remove merge source gaps from range used for merge notifications.
3611    See http://subversion.tigris.org/issues/show_bug.cgi?id=4138
3612
3613    If IMPLICIT_SRC_GAP is not NULL then it is a rangelist containing a
3614    single range (see the implicit_src_gap member of merge_cmd_baton_t).
3615    RANGE describes a (possibly reverse) merge.
3616
3617    If IMPLICIT_SRC_GAP is not NULL and it's sole range intersects with
3618    the older revision in *RANGE, then remove IMPLICIT_SRC_GAP's range
3619    from *RANGE. */
3620 static void
3621 remove_source_gap(svn_merge_range_t *range,
3622                   apr_array_header_t *implicit_src_gap)
3623 {
3624   if (implicit_src_gap)
3625     {
3626       svn_merge_range_t *gap_range =
3627         APR_ARRAY_IDX(implicit_src_gap, 0, svn_merge_range_t *);
3628       if (range->start < range->end)
3629         {
3630           if (gap_range->start == range->start)
3631             range->start = gap_range->end;
3632         }
3633       else /* Reverse merge */
3634         {
3635           if (gap_range->start == range->end)
3636             range->end = gap_range->end;
3637         }
3638     }
3639 }
3640
3641 /* Notify that we're starting a merge
3642  *
3643  * This calls the client's notification receiver (as found in the client
3644  * context), with a WC abspath.
3645  */
3646 static svn_error_t *
3647 notify_merge_begin(merge_cmd_baton_t *merge_b,
3648                    const char *local_abspath,
3649                    svn_boolean_t delete_action,
3650                    apr_pool_t *scratch_pool)
3651 {
3652   svn_wc_notify_t *notify;
3653   svn_merge_range_t n_range =
3654     {SVN_INVALID_REVNUM, SVN_INVALID_REVNUM, TRUE};
3655   const char *notify_abspath;
3656
3657   if (! merge_b->ctx->notify_func2)
3658     return SVN_NO_ERROR;
3659
3660   /* If our merge sources are ancestors of one another... */
3661   if (merge_b->merge_source.ancestral)
3662     {
3663       const svn_client__merge_path_t *child;
3664       /* Find NOTIFY->PATH's nearest ancestor in
3665          NOTIFY->CHILDREN_WITH_MERGEINFO.  Normally we consider a child in
3666          NOTIFY->CHILDREN_WITH_MERGEINFO representing PATH to be an
3667          ancestor of PATH, but if this is a deletion of PATH then the
3668          notification must be for a proper ancestor of PATH.  This ensures
3669          we don't get notifications like:
3670
3671            --- Merging rX into 'PARENT/CHILD'
3672            D    PARENT/CHILD
3673
3674          But rather:
3675
3676            --- Merging rX into 'PARENT'
3677            D    PARENT/CHILD
3678       */
3679
3680       child = find_nearest_ancestor_with_intersecting_ranges(
3681         &(n_range.start), &(n_range.end),
3682         merge_b->notify_begin.nodes_with_mergeinfo,
3683         ! delete_action, local_abspath);
3684
3685       if (!child && delete_action)
3686         {
3687           /* Triggered by file replace in single-file-merge */
3688           child = find_nearest_ancestor(merge_b->notify_begin.nodes_with_mergeinfo,
3689                                         TRUE, local_abspath);
3690         }
3691
3692       assert(child != NULL); /* Should always find the merge anchor */
3693
3694       if (! child)
3695         return SVN_NO_ERROR;
3696
3697       if (merge_b->notify_begin.last_abspath != NULL
3698           && strcmp(child->abspath, merge_b->notify_begin.last_abspath) == 0)
3699         {
3700           /* Don't notify the same merge again */
3701           return SVN_NO_ERROR;
3702         }
3703
3704       merge_b->notify_begin.last_abspath = child->abspath;
3705
3706       if (child->absent || child->remaining_ranges->nelts == 0
3707           || !SVN_IS_VALID_REVNUM(n_range.start))
3708         {
3709           /* No valid information for an header */
3710           return SVN_NO_ERROR;
3711         }
3712
3713       notify_abspath = child->abspath;
3714     }
3715   else
3716     {
3717       if (merge_b->notify_begin.last_abspath)
3718         return SVN_NO_ERROR; /* already notified */
3719
3720       notify_abspath = merge_b->target->abspath;
3721       /* Store something in last_abspath. Any value would do */
3722       merge_b->notify_begin.last_abspath = merge_b->target->abspath;
3723     }
3724
3725   notify = svn_wc_create_notify(notify_abspath,
3726                                 merge_b->same_repos
3727                                       ? svn_wc_notify_merge_begin
3728                                       : svn_wc_notify_foreign_merge_begin,
3729                                 scratch_pool);
3730
3731   if (SVN_IS_VALID_REVNUM(n_range.start))
3732     {
3733       /* If the merge source has a gap, then don't mention
3734          those gap revisions in the notification. */
3735       remove_source_gap(&n_range, merge_b->implicit_src_gap);
3736       notify->merge_range = &n_range;
3737     }
3738   else
3739     {
3740       notify->merge_range = NULL;
3741     }
3742
3743   merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2, notify,
3744                              scratch_pool);
3745
3746   return SVN_NO_ERROR;
3747 }
3748
3749 /* Set *OUT_RANGELIST to the intersection of IN_RANGELIST with the simple
3750  * (inheritable) revision range REV1:REV2, according to CONSIDER_INHERITANCE.
3751  * If REV1 is equal to REV2, the result is an empty rangelist, otherwise
3752  * REV1 must be less than REV2.
3753  *
3754  * Note: If CONSIDER_INHERITANCE is FALSE, the effect is to treat any non-
3755  * inheritable input ranges as if they were inheritable.  If it is TRUE, the
3756  * effect is to discard any non-inheritable input ranges.  Therefore the
3757  * ranges in *OUT_RANGELIST will always be inheritable. */
3758 static svn_error_t *
3759 rangelist_intersect_range(svn_rangelist_t **out_rangelist,
3760                           const svn_rangelist_t *in_rangelist,
3761                           svn_revnum_t rev1,
3762                           svn_revnum_t rev2,
3763                           svn_boolean_t consider_inheritance,
3764                           apr_pool_t *result_pool,
3765                           apr_pool_t *scratch_pool)
3766 {
3767   SVN_ERR_ASSERT(rev1 <= rev2);
3768
3769   if (rev1 < rev2)
3770     {
3771       svn_rangelist_t *simple_rangelist =
3772         svn_rangelist__initialize(rev1, rev2, TRUE, scratch_pool);
3773
3774       SVN_ERR(svn_rangelist_intersect(out_rangelist,
3775                                       simple_rangelist, in_rangelist,
3776                                       consider_inheritance, result_pool));
3777     }
3778   else
3779     {
3780       *out_rangelist = apr_array_make(result_pool, 0,
3781                                       sizeof(svn_merge_range_t *));
3782     }
3783   return SVN_NO_ERROR;
3784 }
3785
3786 /* Helper for fix_deleted_subtree_ranges().  Like fix_deleted_subtree_ranges()
3787    this function should only be called when honoring mergeinfo.
3788
3789    CHILD, PARENT, REVISION1, REVISION2, and RA_SESSION are all cascaded from
3790    fix_deleted_subtree_ranges() -- see that function for more information on
3791    each.
3792
3793    If PARENT is not the merge target then PARENT must have already have been
3794    processed by this function as a child.  Specifically, this means that
3795    PARENT->REMAINING_RANGES must already be populated -- it can be an empty
3796    rangelist but cannot be NULL.
3797
3798    PRIMARY_URL is the merge source url of CHILD at the younger of REVISION1
3799    and REVISION2.
3800
3801    Since this function is only invoked for subtrees of the merge target, the
3802    guarantees afforded by normalize_merge_sources() don't apply - see the
3803    'MERGEINFO MERGE SOURCE NORMALIZATION' comment at the top of this file.
3804    Therefore it is possible that PRIMARY_URL@REVISION1 and
3805    PRIMARY_URL@REVISION2 don't describe the endpoints of an unbroken line of
3806    history.  The purpose of this helper is to identify these cases of broken
3807    history and adjust CHILD->REMAINING_RANGES in such a way we don't later try
3808    to describe nonexistent path/revisions to the merge report editor -- see
3809    drive_merge_report_editor().
3810
3811    If PRIMARY_URL@REVISION1 and PRIMARY_URL@REVISION2 describe an unbroken
3812    line of history then do nothing and leave CHILD->REMAINING_RANGES as-is.
3813
3814    If neither PRIMARY_URL@REVISION1 nor PRIMARY_URL@REVISION2 exist then
3815    there is nothing to merge to CHILD->ABSPATH so set CHILD->REMAINING_RANGES
3816    equal to PARENT->REMAINING_RANGES.  This will cause the subtree to
3817    effectively ignore CHILD -- see 'Note: If the first svn_merge_range_t...'
3818    in drive_merge_report_editor()'s doc string.
3819
3820    If PRIMARY_URL@REVISION1 *xor* PRIMARY_URL@REVISION2 exist then we take the
3821    subset of REVISION1:REVISION2 in CHILD->REMAINING_RANGES at which
3822    PRIMARY_URL doesn't exist and set that subset equal to
3823    PARENT->REMAINING_RANGES' intersection with that non-existent range.  Why?
3824    Because this causes CHILD->REMAINING_RANGES to be identical to
3825    PARENT->REMAINING_RANGES for revisions between REVISION1 and REVISION2 at
3826    which PRIMARY_URL doesn't exist.  As mentioned above this means that
3827    drive_merge_report_editor() won't attempt to describe these non-existent
3828    subtree path/ranges to the reporter (which would break the merge).
3829
3830    If the preceding paragraph wasn't terribly clear then what follows spells
3831    out this function's behavior a bit more explicitly:
3832
3833    For forward merges (REVISION1 < REVISION2)
3834
3835      If PRIMARY_URL@REVISION1 exists but PRIMARY_URL@REVISION2 doesn't, then
3836      find the revision 'N' in which PRIMARY_URL@REVISION1 was deleted.  Leave
3837      the subset of CHILD->REMAINING_RANGES that intersects with
3838      REVISION1:(N - 1) as-is and set the subset of CHILD->REMAINING_RANGES
3839      that intersects with (N - 1):REVISION2 equal to PARENT->REMAINING_RANGES'
3840      intersection with (N - 1):REVISION2.
3841
3842      If PRIMARY_URL@REVISION1 doesn't exist but PRIMARY_URL@REVISION2 does,
3843      then find the revision 'M' in which PRIMARY_URL@REVISION2 came into
3844      existence.  Leave the subset of CHILD->REMAINING_RANGES that intersects with
3845      (M - 1):REVISION2 as-is and set the subset of CHILD->REMAINING_RANGES
3846      that intersects with REVISION1:(M - 1) equal to PARENT->REMAINING_RANGES'
3847      intersection with REVISION1:(M - 1).
3848
3849    For reverse merges (REVISION1 > REVISION2)
3850
3851      If PRIMARY_URL@REVISION1 exists but PRIMARY_URL@REVISION2 doesn't, then
3852      find the revision 'N' in which PRIMARY_URL@REVISION1 came into existence.
3853      Leave the subset of CHILD->REMAINING_RANGES that intersects with
3854      REVISION2:(N - 1) as-is and set the subset of CHILD->REMAINING_RANGES
3855      that intersects with (N - 1):REVISION1 equal to PARENT->REMAINING_RANGES'
3856      intersection with (N - 1):REVISION1.
3857
3858      If PRIMARY_URL@REVISION1 doesn't exist but PRIMARY_URL@REVISION2 does,
3859      then find the revision 'M' in which PRIMARY_URL@REVISION2 came into
3860      existence.  Leave the subset of CHILD->REMAINING_RANGES that intersects with
3861      REVISION2:(M - 1) as-is and set the subset of CHILD->REMAINING_RANGES
3862      that intersects with (M - 1):REVISION1 equal to PARENT->REMAINING_RANGES'
3863      intersection with REVISION1:(M - 1).
3864
3865    SCRATCH_POOL is used for all temporary allocations.  Changes to CHILD are
3866    allocated in RESULT_POOL. */
3867 static svn_error_t *
3868 adjust_deleted_subtree_ranges(svn_client__merge_path_t *child,
3869                               svn_client__merge_path_t *parent,
3870                               svn_revnum_t revision1,
3871                               svn_revnum_t revision2,
3872                               const char *primary_url,
3873                               svn_ra_session_t *ra_session,
3874                               svn_client_ctx_t *ctx,
3875                               apr_pool_t *result_pool,
3876                               apr_pool_t *scratch_pool)
3877 {
3878   svn_boolean_t is_rollback = revision2 < revision1;
3879   svn_revnum_t younger_rev = is_rollback ? revision1 : revision2;
3880   svn_revnum_t peg_rev = younger_rev;
3881   svn_revnum_t older_rev = is_rollback ? revision2 : revision1;
3882   apr_array_header_t *segments;
3883   svn_error_t *err;
3884
3885   SVN_ERR_ASSERT(parent->remaining_ranges);
3886
3887   err = svn_client__repos_location_segments(&segments, ra_session,
3888                                             primary_url, peg_rev,
3889                                             younger_rev, older_rev, ctx,
3890                                             scratch_pool);
3891
3892   if (err)
3893     {
3894       const char *rel_source_path;  /* PRIMARY_URL relative to RA_SESSION */
3895       svn_node_kind_t kind;
3896
3897       if (err->apr_err != SVN_ERR_FS_NOT_FOUND)
3898         return svn_error_trace(err);
3899
3900       svn_error_clear(err);
3901
3902       /* PRIMARY_URL@peg_rev doesn't exist.  Check if PRIMARY_URL@older_rev
3903          exists, if neither exist then the editor can simply ignore this
3904          subtree. */
3905
3906       SVN_ERR(svn_ra_get_path_relative_to_session(
3907                 ra_session, &rel_source_path, primary_url, scratch_pool));
3908
3909       SVN_ERR(svn_ra_check_path(ra_session, rel_source_path,
3910                                 older_rev, &kind, scratch_pool));
3911       if (kind == svn_node_none)
3912         {
3913           /* Neither PRIMARY_URL@peg_rev nor PRIMARY_URL@older_rev exist,
3914              so there is nothing to merge.  Set CHILD->REMAINING_RANGES
3915              identical to PARENT's. */
3916           child->remaining_ranges =
3917             svn_rangelist_dup(parent->remaining_ranges, scratch_pool);
3918         }
3919       else
3920         {
3921           svn_rangelist_t *deleted_rangelist;
3922           svn_revnum_t rev_primary_url_deleted;
3923
3924           /* PRIMARY_URL@older_rev exists, so it was deleted at some
3925              revision prior to peg_rev, find that revision. */
3926           SVN_ERR(svn_ra_get_deleted_rev(ra_session, rel_source_path,
3927                                          older_rev, younger_rev,
3928                                          &rev_primary_url_deleted,
3929                                          scratch_pool));
3930
3931           /* PRIMARY_URL@older_rev exists and PRIMARY_URL@peg_rev doesn't,
3932              so svn_ra_get_deleted_rev() should always find the revision
3933              PRIMARY_URL@older_rev was deleted. */
3934           SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(rev_primary_url_deleted));
3935
3936           /* If this is a reverse merge reorder CHILD->REMAINING_RANGES and
3937              PARENT->REMAINING_RANGES so both will work with the
3938              svn_rangelist_* APIs below. */
3939           if (is_rollback)
3940             {
3941               /* svn_rangelist_reverse operates in place so it's safe
3942                  to use our scratch_pool. */
3943               SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
3944                                             scratch_pool));
3945               SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
3946                                             scratch_pool));
3947             }
3948
3949           /* Find the intersection of CHILD->REMAINING_RANGES with the
3950              range over which PRIMARY_URL@older_rev exists (ending at
3951              the youngest revision at which it still exists). */
3952           SVN_ERR(rangelist_intersect_range(&child->remaining_ranges,
3953                                             child->remaining_ranges,
3954                                             older_rev,
3955                                             rev_primary_url_deleted - 1,
3956                                             FALSE,
3957                                             scratch_pool, scratch_pool));
3958
3959           /* Merge into CHILD->REMAINING_RANGES the intersection of
3960              PARENT->REMAINING_RANGES with the range beginning when
3961              PRIMARY_URL@older_rev was deleted until younger_rev. */
3962           SVN_ERR(rangelist_intersect_range(&deleted_rangelist,
3963                                             parent->remaining_ranges,
3964                                             rev_primary_url_deleted - 1,
3965                                             peg_rev,
3966                                             FALSE,
3967                                             scratch_pool, scratch_pool));
3968           SVN_ERR(svn_rangelist_merge2(child->remaining_ranges,
3969                                        deleted_rangelist, scratch_pool,
3970                                        scratch_pool));
3971
3972           /* Return CHILD->REMAINING_RANGES and PARENT->REMAINING_RANGES
3973              to reverse order if necessary. */
3974           if (is_rollback)
3975             {
3976               SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
3977                                             scratch_pool));
3978               SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
3979                                             scratch_pool));
3980             }
3981         }
3982     }
3983   else /* PRIMARY_URL@peg_rev exists. */
3984     {
3985       svn_rangelist_t *non_existent_rangelist;
3986       svn_location_segment_t *segment =
3987         APR_ARRAY_IDX(segments, (segments->nelts - 1),
3988                       svn_location_segment_t *);
3989
3990       /* We know PRIMARY_URL@peg_rev exists as the call to
3991          svn_client__repos_location_segments() succeeded.  If there is only
3992          one segment that starts at oldest_rev then we know that
3993          PRIMARY_URL@oldest_rev:PRIMARY_URL@peg_rev describes an unbroken
3994          line of history, so there is nothing more to adjust in
3995          CHILD->REMAINING_RANGES. */
3996       if (segment->range_start == older_rev)
3997         {
3998           return SVN_NO_ERROR;
3999         }
4000
4001       /* If this is a reverse merge reorder CHILD->REMAINING_RANGES and
4002          PARENT->REMAINING_RANGES so both will work with the
4003          svn_rangelist_* APIs below. */
4004       if (is_rollback)
4005         {
4006           SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
4007                                         scratch_pool));
4008           SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
4009                                         scratch_pool));
4010         }
4011
4012       /* Intersect CHILD->REMAINING_RANGES with the range where PRIMARY_URL
4013          exists.  Since segment doesn't span older_rev:peg_rev we know
4014          PRIMARY_URL@peg_rev didn't come into existence until
4015          segment->range_start + 1. */
4016       SVN_ERR(rangelist_intersect_range(&child->remaining_ranges,
4017                                         child->remaining_ranges,
4018                                         segment->range_start, peg_rev,
4019                                         FALSE, scratch_pool, scratch_pool));
4020
4021       /* Merge into CHILD->REMAINING_RANGES the intersection of
4022          PARENT->REMAINING_RANGES with the range before PRIMARY_URL@peg_rev
4023          came into existence. */
4024       SVN_ERR(rangelist_intersect_range(&non_existent_rangelist,
4025                                         parent->remaining_ranges,
4026                                         older_rev, segment->range_start,
4027                                         FALSE, scratch_pool, scratch_pool));
4028       SVN_ERR(svn_rangelist_merge2(child->remaining_ranges,
4029                                    non_existent_rangelist, scratch_pool,
4030                                    scratch_pool));
4031
4032       /* Return CHILD->REMAINING_RANGES and PARENT->REMAINING_RANGES
4033          to reverse order if necessary. */
4034       if (is_rollback)
4035         {
4036           SVN_ERR(svn_rangelist_reverse(child->remaining_ranges,
4037                                         scratch_pool));
4038           SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges,
4039                                         scratch_pool));
4040         }
4041     }
4042
4043   /* Make a lasting copy of CHILD->REMAINING_RANGES using POOL. */
4044   child->remaining_ranges = svn_rangelist_dup(child->remaining_ranges,
4045                                               result_pool);
4046   return SVN_NO_ERROR;
4047 }
4048
4049 /* Helper for do_directory_merge().
4050
4051    SOURCE is cascaded from the argument of the same name in
4052    do_directory_merge().  TARGET is the merge target.  RA_SESSION is the
4053    session for the younger of SOURCE->loc1 and SOURCE->loc2.
4054
4055    Adjust the subtrees in CHILDREN_WITH_MERGEINFO so that we don't
4056    later try to describe invalid paths in drive_merge_report_editor().
4057    This function is just a thin wrapper around
4058    adjust_deleted_subtree_ranges(), which see for further details.
4059
4060    SCRATCH_POOL is used for all temporary allocations.  Changes to
4061    CHILDREN_WITH_MERGEINFO are allocated in RESULT_POOL.
4062 */
4063 static svn_error_t *
4064 fix_deleted_subtree_ranges(const merge_source_t *source,
4065                            const merge_target_t *target,
4066                            svn_ra_session_t *ra_session,
4067                            apr_array_header_t *children_with_mergeinfo,
4068                            svn_client_ctx_t *ctx,
4069                            apr_pool_t *result_pool,
4070                            apr_pool_t *scratch_pool)
4071 {
4072   int i;
4073   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
4074   svn_boolean_t is_rollback = source->loc2->rev < source->loc1->rev;
4075
4076   assert(session_url_is(ra_session,
4077                         (is_rollback ? source->loc1 : source->loc2)->url,
4078                         scratch_pool));
4079
4080   /* CHILDREN_WITH_MERGEINFO is sorted in depth-first order, so
4081      start at index 1 to examine only subtrees. */
4082   for (i = 1; i < children_with_mergeinfo->nelts; i++)
4083     {
4084       svn_client__merge_path_t *child =
4085         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
4086       svn_client__merge_path_t *parent;
4087       svn_rangelist_t *deleted_rangelist, *added_rangelist;
4088
4089       SVN_ERR_ASSERT(child);
4090       if (child->absent)
4091         continue;
4092
4093       svn_pool_clear(iterpool);
4094
4095       /* Find CHILD's parent. */
4096       parent = find_nearest_ancestor(children_with_mergeinfo,
4097                                      FALSE, child->abspath);
4098
4099       /* Since CHILD is a subtree then its parent must be in
4100          CHILDREN_WITH_MERGEINFO, see the global comment
4101          'THE CHILDREN_WITH_MERGEINFO ARRAY'. */
4102       SVN_ERR_ASSERT(parent);
4103
4104       /* If this is a reverse merge reorder CHILD->REMAINING_RANGES
4105          so it will work with the svn_rangelist_diff API. */
4106       if (is_rollback)
4107         {
4108           SVN_ERR(svn_rangelist_reverse(child->remaining_ranges, iterpool));
4109           SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges, iterpool));
4110         }
4111
4112       SVN_ERR(svn_rangelist_diff(&deleted_rangelist, &added_rangelist,
4113                                  child->remaining_ranges,
4114                                  parent->remaining_ranges,
4115                                  TRUE, iterpool));
4116
4117       if (is_rollback)
4118         {
4119           SVN_ERR(svn_rangelist_reverse(child->remaining_ranges, iterpool));
4120           SVN_ERR(svn_rangelist_reverse(parent->remaining_ranges, iterpool));
4121         }
4122
4123       /* If CHILD is the merge target we then know that SOURCE is provided
4124          by normalize_merge_sources() -- see 'MERGEINFO MERGE SOURCE
4125          NORMALIZATION'.  Due to this normalization we know that SOURCE
4126          describes an unbroken line of history such that the entire range
4127          described by SOURCE can potentially be merged to CHILD.
4128
4129          But if CHILD is a subtree we don't have the same guarantees about
4130          SOURCE as we do for the merge target.  SOURCE->loc1 and/or
4131          SOURCE->loc2 might not exist.
4132
4133          If one or both doesn't exist, then adjust CHILD->REMAINING_RANGES
4134          such that we don't later try to describe invalid subtrees in
4135          drive_merge_report_editor(), as that will break the merge.
4136          If CHILD has the same remaining ranges as PARENT however, then
4137          there is no need to make these adjustments, since
4138          drive_merge_report_editor() won't attempt to describe CHILD in this
4139          case, see the 'Note' in drive_merge_report_editor's docstring. */
4140       if (deleted_rangelist->nelts || added_rangelist->nelts)
4141         {
4142           const char *child_primary_source_url;
4143           const char *child_repos_src_path =
4144             svn_dirent_is_child(target->abspath, child->abspath, iterpool);
4145
4146           /* This loop is only processing subtrees, so CHILD->ABSPATH
4147              better be a proper child of the merge target. */
4148           SVN_ERR_ASSERT(child_repos_src_path);
4149
4150           child_primary_source_url =
4151             svn_path_url_add_component2((source->loc1->rev < source->loc2->rev)
4152                                         ? source->loc2->url : source->loc1->url,
4153                                         child_repos_src_path, iterpool);
4154
4155           SVN_ERR(adjust_deleted_subtree_ranges(child, parent,
4156                                                 source->loc1->rev,
4157                                                 source->loc2->rev,
4158                                                 child_primary_source_url,
4159                                                 ra_session,
4160                                                 ctx, result_pool, iterpool));
4161         }
4162     }
4163
4164   svn_pool_destroy(iterpool);
4165   return SVN_NO_ERROR;
4166 }
4167
4168 /*-----------------------------------------------------------------------*/
4169 \f
4170 /*** Determining What Remains To Be Merged ***/
4171
4172 /* Get explicit and/or implicit mergeinfo for the working copy path
4173    TARGET_ABSPATH.
4174
4175    If RECORDED_MERGEINFO is not NULL then set *RECORDED_MERGEINFO
4176    to TARGET_ABSPATH's explicit or inherited mergeinfo as dictated by
4177    INHERIT.
4178
4179    If IMPLICIT_MERGEINFO is not NULL then set *IMPLICIT_MERGEINFO
4180    to TARGET_ABSPATH's implicit mergeinfo (a.k.a. natural history).
4181
4182    If both RECORDED_MERGEINFO and IMPLICIT_MERGEINFO are not NULL and
4183    *RECORDED_MERGEINFO is inherited, then *IMPLICIT_MERGEINFO will be
4184    removed from *RECORDED_MERGEINFO.
4185
4186    If INHERITED is not NULL set *INHERITED to TRUE if *RECORDED_MERGEINFO
4187    is inherited rather than explicit.  If RECORDED_MERGEINFO is NULL then
4188    INHERITED is ignored.
4189
4190
4191    If IMPLICIT_MERGEINFO is not NULL then START and END are limits on
4192    the natural history sought, must both be valid revision numbers, and
4193    START must be greater than END.  If TARGET_ABSPATH's base revision
4194    is older than START, then the base revision is used as the younger
4195    bound in place of START.
4196
4197    RA_SESSION is an RA session open to the repository in which TARGET_ABSPATH
4198    lives.  It may be temporarily reparented as needed by this function.
4199
4200    Allocate *RECORDED_MERGEINFO and *IMPLICIT_MERGEINFO in RESULT_POOL.
4201    Use SCRATCH_POOL for any temporary allocations. */
4202 static svn_error_t *
4203 get_full_mergeinfo(svn_mergeinfo_t *recorded_mergeinfo,
4204                    svn_mergeinfo_t *implicit_mergeinfo,
4205                    svn_boolean_t *inherited,
4206                    svn_mergeinfo_inheritance_t inherit,
4207                    svn_ra_session_t *ra_session,
4208                    const char *target_abspath,
4209                    svn_revnum_t start,
4210                    svn_revnum_t end,
4211                    svn_client_ctx_t *ctx,
4212                    apr_pool_t *result_pool,
4213                    apr_pool_t *scratch_pool)
4214 {
4215   /* First, we get the real mergeinfo. */
4216   if (recorded_mergeinfo)
4217     {
4218       SVN_ERR(svn_client__get_wc_or_repos_mergeinfo(recorded_mergeinfo,
4219                                                     inherited,
4220                                                     NULL /* from_repos */,
4221                                                     FALSE,
4222                                                     inherit, ra_session,
4223                                                     target_abspath,
4224                                                     ctx, result_pool));
4225     }
4226
4227   if (implicit_mergeinfo)
4228     {
4229       svn_client__pathrev_t *target;
4230
4231       /* Assert that we have sane input. */
4232       SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(start) && SVN_IS_VALID_REVNUM(end)
4233                      && (start > end));
4234
4235       /* Retrieve the origin (original_*) of the node, or just the
4236          url if the node was not copied. */
4237       SVN_ERR(svn_client__wc_node_get_origin(&target, target_abspath, ctx,
4238                                              scratch_pool, scratch_pool));
4239
4240       if (! target)
4241         {
4242           /* We've been asked to operate on a locally added target, so its
4243            * implicit mergeinfo is empty. */
4244           *implicit_mergeinfo = apr_hash_make(result_pool);
4245         }
4246       else if (target->rev <= end)
4247         {
4248           /* We're asking about a range outside our natural history
4249              altogether.  That means our implicit mergeinfo is empty. */
4250           *implicit_mergeinfo = apr_hash_make(result_pool);
4251         }
4252       else
4253         {
4254           /* Fetch so-called "implicit mergeinfo" (that is, natural
4255              history). */
4256
4257           /* Do not ask for implicit mergeinfo from TARGET_ABSPATH's future.
4258              TARGET_ABSPATH might not even exist, and even if it does the
4259              working copy is *at* TARGET_REV so its implicit history ends
4260              at TARGET_REV! */
4261           if (target->rev < start)
4262             start = target->rev;
4263
4264           /* Fetch the implicit mergeinfo. */
4265           SVN_ERR(svn_client__get_history_as_mergeinfo(implicit_mergeinfo,
4266                                                        NULL,
4267                                                        target, start, end,
4268                                                        ra_session, ctx,
4269                                                        result_pool));
4270         }
4271     } /*if (implicit_mergeinfo) */
4272
4273   return SVN_NO_ERROR;
4274 }
4275
4276 /* Helper for ensure_implicit_mergeinfo().
4277
4278    PARENT, CHILD, REVISION1, REVISION2 and CTX
4279    are all cascaded from the arguments of the same names in
4280    ensure_implicit_mergeinfo().  PARENT and CHILD must both exist, i.e.
4281    this function should never be called where CHILD is the merge target.
4282
4283    If PARENT->IMPLICIT_MERGEINFO is NULL, obtain it from the server.
4284
4285    Set CHILD->IMPLICIT_MERGEINFO to the mergeinfo inherited from
4286    PARENT->IMPLICIT_MERGEINFO.  CHILD->IMPLICIT_MERGEINFO is allocated
4287    in RESULT_POOL.
4288
4289    RA_SESSION is an RA session open to the repository that contains CHILD.
4290    It may be temporarily reparented by this function.
4291    */
4292 static svn_error_t *
4293 inherit_implicit_mergeinfo_from_parent(svn_client__merge_path_t *parent,
4294                                        svn_client__merge_path_t *child,
4295                                        svn_revnum_t revision1,
4296                                        svn_revnum_t revision2,
4297                                        svn_ra_session_t *ra_session,
4298                                        svn_client_ctx_t *ctx,
4299                                        apr_pool_t *result_pool,
4300                                        apr_pool_t *scratch_pool)
4301 {
4302   const char *path_diff;
4303
4304   /* This only works on subtrees! */
4305   SVN_ERR_ASSERT(parent);
4306   SVN_ERR_ASSERT(child);
4307
4308   /* While PARENT must exist, it is possible we've deferred
4309      getting its implicit mergeinfo.  If so get it now. */
4310   if (!parent->implicit_mergeinfo)
4311     SVN_ERR(get_full_mergeinfo(NULL, &(parent->implicit_mergeinfo),
4312                                NULL, svn_mergeinfo_inherited,
4313                                ra_session, child->abspath,
4314                                MAX(revision1, revision2),
4315                                MIN(revision1, revision2),
4316                                ctx, result_pool, scratch_pool));
4317
4318   /* Let CHILD inherit PARENT's implicit mergeinfo. */
4319
4320   path_diff = svn_dirent_is_child(parent->abspath, child->abspath,
4321                                   scratch_pool);
4322   /* PARENT->PATH better be an ancestor of CHILD->ABSPATH! */
4323   SVN_ERR_ASSERT(path_diff);
4324
4325   SVN_ERR(svn_mergeinfo__add_suffix_to_mergeinfo(
4326             &child->implicit_mergeinfo, parent->implicit_mergeinfo,
4327             path_diff, result_pool, scratch_pool));
4328   child->implicit_mergeinfo = svn_mergeinfo_dup(child->implicit_mergeinfo,
4329                                                 result_pool);
4330   return SVN_NO_ERROR;
4331 }
4332
4333 /* Helper of filter_merged_revisions().
4334
4335    If we have deferred obtaining CHILD->IMPLICIT_MERGEINFO, then get
4336    it now, allocating it in RESULT_POOL.  If CHILD_INHERITS_PARENT is true
4337    then set CHILD->IMPLICIT_MERGEINFO to the mergeinfo inherited from
4338    PARENT->IMPLICIT_MERGEINFO, otherwise contact the repository.  Use
4339    SCRATCH_POOL for all temporary allocations.
4340
4341    RA_SESSION is an RA session open to the repository that contains CHILD.
4342    It may be temporarily reparented by this function.
4343
4344    PARENT, CHILD, REVISION1, REVISION2 and
4345    CTX are all cascaded from the arguments of the same name in
4346    filter_merged_revisions() and the same conditions for that function
4347    hold here. */
4348 static svn_error_t *
4349 ensure_implicit_mergeinfo(svn_client__merge_path_t *parent,
4350                           svn_client__merge_path_t *child,
4351                           svn_boolean_t child_inherits_parent,
4352                           svn_revnum_t revision1,
4353                           svn_revnum_t revision2,
4354                           svn_ra_session_t *ra_session,
4355                           svn_client_ctx_t *ctx,
4356                           apr_pool_t *result_pool,
4357                           apr_pool_t *scratch_pool)
4358 {
4359   /* If we haven't already found CHILD->IMPLICIT_MERGEINFO then
4360      contact the server to get it. */
4361
4362   if (child->implicit_mergeinfo)
4363     return SVN_NO_ERROR;
4364
4365   if (child_inherits_parent)
4366     SVN_ERR(inherit_implicit_mergeinfo_from_parent(parent,
4367                                                    child,
4368                                                    revision1,
4369                                                    revision2,
4370                                                    ra_session,
4371                                                    ctx,
4372                                                    result_pool,
4373                                                    scratch_pool));
4374   else
4375     SVN_ERR(get_full_mergeinfo(NULL,
4376                                &(child->implicit_mergeinfo),
4377                                NULL, svn_mergeinfo_inherited,
4378                                ra_session, child->abspath,
4379                                MAX(revision1, revision2),
4380                                MIN(revision1, revision2),
4381                                ctx, result_pool, scratch_pool));
4382
4383   return SVN_NO_ERROR;
4384 }
4385
4386 /* Helper for calculate_remaining_ranges().
4387
4388    Initialize CHILD->REMAINING_RANGES to a rangelist representing the
4389    requested merge of REVISION1:REVISION2 from MERGEINFO_PATH to
4390    CHILD->ABSPATH.
4391
4392    For forward merges remove any ranges from CHILD->REMAINING_RANGES that
4393    have already been merged to CHILD->ABSPATH per TARGET_MERGEINFO or
4394    CHILD->IMPLICIT_MERGEINFO.  For reverse merges remove any ranges from
4395    CHILD->REMAINING_RANGES that have not already been merged to CHILD->ABSPATH
4396    per TARGET_MERGEINFO or CHILD->IMPLICIT_MERGEINFO.  If we have deferred
4397    obtaining CHILD->IMPLICIT_MERGEINFO and it is necessary to use it for
4398    these calculations, then get it from the server, allocating it in
4399    RESULT_POOL.
4400
4401    CHILD represents a working copy path which is the merge target or one of
4402    the target's subtrees.  If not NULL, PARENT is CHILD's nearest path-wise
4403    ancestor - see 'THE CHILDREN_WITH_MERGEINFO ARRAY'.
4404
4405    If the function needs to consider CHILD->IMPLICIT_MERGEINFO and
4406    CHILD_INHERITS_IMPLICIT is true, then set CHILD->IMPLICIT_MERGEINFO to the
4407    mergeinfo inherited from PARENT->IMPLICIT_MERGEINFO.  Otherwise contact
4408    the repository for CHILD->IMPLICIT_MERGEINFO.
4409
4410    NOTE: If PARENT is present then this function must have previously been
4411    called for PARENT, i.e. if populate_remaining_ranges() is calling this
4412    function for a set of svn_client__merge_path_t* the calls must be made
4413    in depth-first order.
4414
4415    MERGEINFO_PATH is the merge source relative to the repository root.
4416
4417    REVISION1 and REVISION2 describe the merge range requested from
4418    MERGEINFO_PATH.
4419
4420    TARGET_RANGELIST is the portion of CHILD->ABSPATH's explicit or inherited
4421    mergeinfo that intersects with the merge history described by
4422    MERGEINFO_PATH@REVISION1:MERGEINFO_PATH@REVISION2.  TARGET_RANGELIST
4423    should be NULL if there is no explicit or inherited mergeinfo on
4424    CHILD->ABSPATH or an empty list if CHILD->ABSPATH has empty mergeinfo or
4425    explicit mergeinfo that exclusively describes non-intersecting history
4426    with MERGEINFO_PATH@REVISION1:MERGEINFO_PATH@REVISION2.
4427
4428    SCRATCH_POOL is used for all temporary allocations.
4429
4430    NOTE: This should only be called when honoring mergeinfo.
4431
4432    NOTE: Like calculate_remaining_ranges() if PARENT is present then this
4433    function must have previously been called for PARENT.
4434 */
4435 static svn_error_t *
4436 filter_merged_revisions(svn_client__merge_path_t *parent,
4437                         svn_client__merge_path_t *child,
4438                         const char *mergeinfo_path,
4439                         svn_rangelist_t *target_rangelist,
4440                         svn_revnum_t revision1,
4441                         svn_revnum_t revision2,
4442                         svn_boolean_t child_inherits_implicit,
4443                         svn_ra_session_t *ra_session,
4444                         svn_client_ctx_t *ctx,
4445                         apr_pool_t *result_pool,
4446                         apr_pool_t *scratch_pool)
4447 {
4448   svn_rangelist_t *requested_rangelist,
4449     *target_implicit_rangelist, *explicit_rangelist;
4450
4451   /* Convert REVISION1 and REVISION2 to a rangelist.
4452
4453      Note: Talking about a requested merge range's inheritability
4454      doesn't make much sense, but as we are using svn_merge_range_t
4455      to describe it we need to pick *something*.  Since all the
4456      rangelist manipulations in this function either don't consider
4457      inheritance by default or we are requesting that they don't (i.e.
4458      svn_rangelist_remove and svn_rangelist_intersect) then we could
4459      set the inheritability as FALSE, it won't matter either way. */
4460   requested_rangelist = svn_rangelist__initialize(revision1, revision2,
4461                                                   TRUE, scratch_pool);
4462
4463   /* Now filter out revisions that have already been merged to CHILD. */
4464
4465   if (revision1 > revision2) /* This is a reverse merge. */
4466     {
4467       svn_rangelist_t *added_rangelist, *deleted_rangelist;
4468
4469       /* The revert range and will need to be reversed for
4470          our svn_rangelist_* APIs to work properly. */
4471       SVN_ERR(svn_rangelist_reverse(requested_rangelist, scratch_pool));
4472
4473       /* Set EXPLICIT_RANGELIST to the list of source-range revs that are
4474          already recorded as merged to target. */
4475       if (target_rangelist)
4476         {
4477           /* Return the intersection of the revs which are both already
4478              represented by CHILD's explicit or inherited mergeinfo.
4479
4480              We don't consider inheritance when determining intersecting
4481              ranges.  If we *did* consider inheritance, then our calculation
4482              would be wrong.  For example, if the CHILD->REMAINING_RANGES is
4483              5:3 and TARGET_RANGELIST is r5* (non-inheritable) then the
4484              intersection would be r4.  And that would be wrong as we clearly
4485              want to reverse merge both r4 and r5 in this case.  Ignoring the
4486              ranges' inheritance results in an intersection of r4-5.
4487
4488              You might be wondering about CHILD's children, doesn't the above
4489              imply that we will reverse merge r4-5 from them?  Nope, this is
4490              safe to do because any path whose parent has non-inheritable
4491              ranges is always considered a subtree with differing mergeinfo
4492              even if that path has no explicit mergeinfo prior to the
4493              merge -- See condition 3 in the doc string for
4494              merge.c:get_mergeinfo_paths(). */
4495           SVN_ERR(svn_rangelist_intersect(&explicit_rangelist,
4496                                           target_rangelist,
4497                                           requested_rangelist,
4498                                           FALSE, scratch_pool));
4499         }
4500       else
4501         {
4502           explicit_rangelist =
4503             apr_array_make(result_pool, 0, sizeof(svn_merge_range_t *));
4504         }
4505
4506       /* Was any part of the requested reverse merge not accounted for in
4507          CHILD's explicit or inherited mergeinfo? */
4508       SVN_ERR(svn_rangelist_diff(&deleted_rangelist, &added_rangelist,
4509                                  requested_rangelist, explicit_rangelist,
4510                                  FALSE, scratch_pool));
4511
4512       if (deleted_rangelist->nelts == 0)
4513         {
4514           /* The whole of REVISION1:REVISION2 was represented in CHILD's
4515              explicit/inherited mergeinfo, allocate CHILD's remaining
4516              ranges in POOL and then we are done. */
4517           SVN_ERR(svn_rangelist_reverse(requested_rangelist, scratch_pool));
4518           child->remaining_ranges = svn_rangelist_dup(requested_rangelist,
4519                                                       result_pool);
4520         }
4521       else /* We need to check CHILD's implicit mergeinfo. */
4522         {
4523           svn_rangelist_t *implicit_rangelist;
4524
4525           SVN_ERR(ensure_implicit_mergeinfo(parent,
4526                                             child,
4527                                             child_inherits_implicit,
4528                                             revision1,
4529                                             revision2,
4530                                             ra_session,
4531                                             ctx,
4532                                             result_pool,
4533                                             scratch_pool));
4534
4535           target_implicit_rangelist = svn_hash_gets(child->implicit_mergeinfo,
4536                                                     mergeinfo_path);
4537
4538           if (target_implicit_rangelist)
4539             SVN_ERR(svn_rangelist_intersect(&implicit_rangelist,
4540                                             target_implicit_rangelist,
4541                                             requested_rangelist,
4542                                             FALSE, scratch_pool));
4543           else
4544             implicit_rangelist = apr_array_make(scratch_pool, 0,
4545                                                 sizeof(svn_merge_range_t *));
4546
4547           SVN_ERR(svn_rangelist_merge2(implicit_rangelist,
4548                                        explicit_rangelist, scratch_pool,
4549                                        scratch_pool));
4550           SVN_ERR(svn_rangelist_reverse(implicit_rangelist, scratch_pool));
4551           child->remaining_ranges = svn_rangelist_dup(implicit_rangelist,
4552                                                       result_pool);
4553         }
4554     }
4555   else /* This is a forward merge */
4556     {
4557       /* Set EXPLICIT_RANGELIST to the list of source-range revs that are
4558          NOT already recorded as merged to target. */
4559       if (target_rangelist)
4560         {
4561           /* See earlier comment preceding svn_rangelist_intersect() for
4562              why we don't consider inheritance here. */
4563           SVN_ERR(svn_rangelist_remove(&explicit_rangelist,
4564                                        target_rangelist,
4565                                        requested_rangelist, FALSE,
4566                                        scratch_pool));
4567         }
4568       else
4569         {
4570           explicit_rangelist = svn_rangelist_dup(requested_rangelist,
4571                                                  scratch_pool);
4572         }
4573
4574       if (explicit_rangelist->nelts == 0)
4575         {
4576           child->remaining_ranges =
4577             apr_array_make(result_pool, 0, sizeof(svn_merge_range_t *));
4578         }
4579       else
4580 /* ### TODO:  Which evil shall we choose?
4581    ###
4582    ### If we allow all forward-merges not already found in recorded
4583    ### mergeinfo, we destroy the ability to, say, merge the whole of a
4584    ### branch to the trunk while automatically ignoring the revisions
4585    ### common to both.  That's bad.
4586    ###
4587    ### If we allow only forward-merges not found in either recorded
4588    ### mergeinfo or implicit mergeinfo (natural history), then the
4589    ### previous scenario works great, but we can't reverse-merge a
4590    ### previous change made to our line of history and then remake it
4591    ### (because the reverse-merge will leave no mergeinfo trace, and
4592    ### the remake-it attempt will still find the original change in
4593    ### natural mergeinfo.  But you know, that we happen to use 'merge'
4594    ### for revision undoing is somewhat unnatural anyway, so I'm
4595    ### finding myself having little interest in caring too much about
4596    ### this.  That said, if we had a way of storing reverse merge
4597    ### ranges, we'd be in good shape either way.
4598 */
4599 #ifdef SVN_MERGE__ALLOW_ALL_FORWARD_MERGES_FROM_SELF
4600         {
4601           /* ### Don't consider implicit mergeinfo. */
4602           child->remaining_ranges = svn_rangelist_dup(explicit_rangelist,
4603                                                       pool);
4604         }
4605 #else
4606         {
4607           /* Based on CHILD's TARGET_MERGEINFO there are ranges to merge.
4608              Check CHILD's implicit mergeinfo to see if these remaining
4609              ranges are represented there. */
4610           SVN_ERR(ensure_implicit_mergeinfo(parent,
4611                                             child,
4612                                             child_inherits_implicit,
4613                                             revision1,
4614                                             revision2,
4615                                             ra_session,
4616                                             ctx,
4617                                             result_pool,
4618                                             scratch_pool));
4619
4620           target_implicit_rangelist = svn_hash_gets(child->implicit_mergeinfo,
4621                                                     mergeinfo_path);
4622           if (target_implicit_rangelist)
4623             SVN_ERR(svn_rangelist_remove(&(child->remaining_ranges),
4624                                          target_implicit_rangelist,
4625                                          explicit_rangelist,
4626                                          FALSE, result_pool));
4627           else
4628             child->remaining_ranges = svn_rangelist_dup(explicit_rangelist,
4629                                                         result_pool);
4630         }
4631 #endif
4632     }
4633
4634   return SVN_NO_ERROR;
4635 }
4636
4637 /* Helper for do_file_merge and do_directory_merge (by way of
4638    populate_remaining_ranges() for the latter).
4639
4640    Determine what portions of SOURCE have already
4641    been merged to CHILD->ABSPATH and populate CHILD->REMAINING_RANGES with
4642    the ranges that still need merging.
4643
4644    SOURCE and CTX are all cascaded from the caller's arguments of the same
4645    names.  Note that this means SOURCE adheres to the requirements noted in
4646    `MERGEINFO MERGE SOURCE NORMALIZATION'.
4647
4648    CHILD represents a working copy path which is the merge target or one of
4649    the target's subtrees.  If not NULL, PARENT is CHILD's nearest path-wise
4650    ancestor - see 'THE CHILDREN_WITH_MERGEINFO ARRAY'.  TARGET_MERGEINFO is
4651    the working mergeinfo on CHILD.
4652
4653    RA_SESSION is the session for the younger of SOURCE->loc1 and
4654    SOURCE->loc2.
4655
4656    If the function needs to consider CHILD->IMPLICIT_MERGEINFO and
4657    CHILD_INHERITS_IMPLICIT is true, then set CHILD->IMPLICIT_MERGEINFO to the
4658    mergeinfo inherited from PARENT->IMPLICIT_MERGEINFO.  Otherwise contact
4659    the repository for CHILD->IMPLICIT_MERGEINFO.
4660
4661    If not null, IMPLICIT_SRC_GAP is the gap, if any, in the natural history
4662    of SOURCE, see merge_cmd_baton_t.implicit_src_gap.
4663
4664    SCRATCH_POOL is used for all temporary allocations.  Changes to CHILD and
4665    PARENT are made in RESULT_POOL.
4666
4667    NOTE: This should only be called when honoring mergeinfo.
4668
4669    NOTE: If PARENT is present then this function must have previously been
4670    called for PARENT, i.e. if populate_remaining_ranges() is calling this
4671    function for a set of svn_client__merge_path_t* the calls must be made
4672    in depth-first order.
4673
4674    NOTE: When performing reverse merges, return
4675    SVN_ERR_CLIENT_NOT_READY_TO_MERGE if both locations in SOURCE and
4676    CHILD->ABSPATH are all on the same line of history but CHILD->ABSPATH's
4677    base revision is older than the SOURCE->rev1:rev2 range, see comment re
4678    issue #2973 below.
4679 */
4680 static svn_error_t *
4681 calculate_remaining_ranges(svn_client__merge_path_t *parent,
4682                            svn_client__merge_path_t *child,
4683                            const merge_source_t *source,
4684                            svn_mergeinfo_t target_mergeinfo,
4685                            const apr_array_header_t *implicit_src_gap,
4686                            svn_boolean_t child_inherits_implicit,
4687                            svn_ra_session_t *ra_session,
4688                            svn_client_ctx_t *ctx,
4689                            apr_pool_t *result_pool,
4690                            apr_pool_t *scratch_pool)
4691 {
4692   const svn_client__pathrev_t *primary_src
4693     = (source->loc1->rev < source->loc2->rev) ? source->loc2 : source->loc1;
4694   const char *mergeinfo_path = svn_client__pathrev_fspath(primary_src,
4695                                                           scratch_pool);
4696   /* Intersection of TARGET_MERGEINFO and the merge history
4697      described by SOURCE. */
4698   svn_rangelist_t *target_rangelist;
4699   svn_revnum_t child_base_revision;
4700
4701   /* Since this function should only be called when honoring mergeinfo and
4702    * SOURCE adheres to the requirements noted in 'MERGEINFO MERGE SOURCE
4703    * NORMALIZATION', SOURCE must be 'ancestral'. */
4704   SVN_ERR_ASSERT(source->ancestral);
4705
4706   /* Determine which of the requested ranges to consider merging... */
4707
4708   /* Set TARGET_RANGELIST to the portion of TARGET_MERGEINFO that refers
4709      to SOURCE (excluding any gap in SOURCE): first get all ranges from
4710      TARGET_MERGEINFO that refer to the path of SOURCE, and then prune
4711      any ranges that lie in the gap in SOURCE.
4712
4713      ### [JAF] In fact, that may still leave some ranges that lie entirely
4714      outside the range of SOURCE; it seems we don't care about that.  */
4715   if (target_mergeinfo)
4716     target_rangelist = svn_hash_gets(target_mergeinfo, mergeinfo_path);
4717   else
4718     target_rangelist = NULL;
4719   if (implicit_src_gap && target_rangelist)
4720     {
4721       /* Remove any mergeinfo referring to the 'gap' in SOURCE, as that
4722          mergeinfo doesn't really refer to SOURCE at all but instead
4723          refers to locations that are non-existent or on a different
4724          line of history.  (Issue #3242.) */
4725       SVN_ERR(svn_rangelist_remove(&target_rangelist,
4726                                    implicit_src_gap, target_rangelist,
4727                                    FALSE, result_pool));
4728     }
4729
4730   /* Initialize CHILD->REMAINING_RANGES and filter out revisions already
4731      merged (or, in the case of reverse merges, ranges not yet merged). */
4732   SVN_ERR(filter_merged_revisions(parent, child, mergeinfo_path,
4733                                   target_rangelist,
4734                                   source->loc1->rev, source->loc2->rev,
4735                                   child_inherits_implicit,
4736                                   ra_session, ctx, result_pool,
4737                                   scratch_pool));
4738
4739   /* Issue #2973 -- from the continuing series of "Why, since the advent of
4740      merge tracking, allowing merges into mixed rev and locally modified
4741      working copies isn't simple and could be considered downright evil".
4742
4743      If reverse merging a range to the WC path represented by CHILD, from
4744      that path's own history, where the path inherits no locally modified
4745      mergeinfo from its WC parents (i.e. there is no uncommitted merge to
4746      the WC), and the path's base revision is older than the range, then
4747      the merge will always be a no-op.  This is because we only allow reverse
4748      merges of ranges in the path's explicit or natural mergeinfo and a
4749      reverse merge from the path's future history obviously isn't going to be
4750      in either, hence the no-op.
4751
4752      The problem is two-fold.  First, in a mixed rev WC, the change we
4753      want to revert might actually be to some child of the target path
4754      which is at a younger base revision.  Sure, we can merge directly
4755      to that child or update the WC or even use --ignore-ancestry and then
4756      successfully run the reverse merge, but that gets to the second
4757      problem: Those courses of action are not very obvious.  Before 1.5 if
4758      a user committed a change that didn't touch the commit target, then
4759      immediately decided to revert that change via a reverse merge it would
4760      just DTRT.  But with the advent of merge tracking the user gets a no-op.
4761
4762      So in the name of user friendliness, return an error suggesting a helpful
4763      course of action.
4764   */
4765   SVN_ERR(svn_wc__node_get_base(NULL, &child_base_revision,
4766                                 NULL, NULL, NULL, NULL,
4767                                 ctx->wc_ctx, child->abspath,
4768                                 TRUE /* ignore_enoent */,
4769                                 scratch_pool, scratch_pool));
4770   /* If CHILD has no base revision then it hasn't been committed yet, so it
4771      can't have any "future" history. */
4772   if (SVN_IS_VALID_REVNUM(child_base_revision)
4773       && ((child->remaining_ranges)->nelts == 0) /* Inoperative merge */
4774       && (source->loc2->rev < source->loc1->rev)     /* Reverse merge */
4775       && (child_base_revision <= source->loc2->rev))  /* From CHILD's future */
4776     {
4777       /* Hmmm, an inoperative reverse merge from the "future".  If it is
4778          from our own future return a helpful error. */
4779       svn_error_t *err;
4780       svn_client__pathrev_t *start_loc;
4781
4782       err = svn_client__repos_location(&start_loc,
4783                                        ra_session,
4784                                        source->loc1,
4785                                        child_base_revision,
4786                                        ctx, scratch_pool, scratch_pool);
4787       if (err)
4788         {
4789           if (err->apr_err == SVN_ERR_FS_NOT_FOUND
4790               || err->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES)
4791             svn_error_clear(err);
4792           else
4793             return svn_error_trace(err);
4794         }
4795       else
4796         {
4797           const char *url;
4798
4799           SVN_ERR(svn_wc__node_get_url(&url, ctx->wc_ctx, child->abspath,
4800                                        scratch_pool, scratch_pool));
4801           if (strcmp(start_loc->url, url) == 0)
4802             return svn_error_create(SVN_ERR_CLIENT_MERGE_UPDATE_REQUIRED, NULL,
4803                                     _("Cannot reverse-merge a range from a "
4804                                       "path's own future history; try "
4805                                       "updating first"));
4806         }
4807     }
4808
4809   return SVN_NO_ERROR;
4810 }
4811
4812 /* Helper for populate_remaining_ranges().
4813
4814    SOURCE is cascaded from the arguments of the same name in
4815    populate_remaining_ranges().
4816
4817    Note: The following comments assume a forward merge, i.e.
4818    SOURCE->loc1->rev < SOURCE->loc2->rev.  If this is a reverse merge then
4819    all the following comments still apply, but with SOURCE->loc1 switched
4820    with SOURCE->loc2.
4821
4822    Like populate_remaining_ranges(), SOURCE must adhere to the restrictions
4823    documented in 'MERGEINFO MERGE SOURCE NORMALIZATION'.  These restrictions
4824    allow for a *single* gap in SOURCE, GAP_REV1:GAP_REV2 exclusive:inclusive
4825    (where SOURCE->loc1->rev == GAP_REV1 <= GAP_REV2 < SOURCE->loc2->rev),
4826    if SOURCE->loc2->url@(GAP_REV2+1) was copied from SOURCE->loc1.  If such
4827    a gap exists, set *GAP_START and *GAP_END to the starting and ending
4828    revisions of the gap.  Otherwise set both to SVN_INVALID_REVNUM.
4829
4830    For example, if the natural history of URL@2:URL@9 is 'trunk/:2,7-9' this
4831    would indicate that trunk@7 was copied from trunk@2.  This function would
4832    return GAP_START:GAP_END of 2:6 in this case.  Note that a path 'trunk'
4833    might exist at r3-6, but it would not be on the same line of history as
4834    trunk@9.
4835
4836    ### GAP_START is basically redundant, as (if there is a gap at all) it is
4837    necessarily the older revision of SOURCE.
4838
4839    RA_SESSION is an open RA session to the repository in which SOURCE lives.
4840 */
4841 static svn_error_t *
4842 find_gaps_in_merge_source_history(svn_revnum_t *gap_start,
4843                                   svn_revnum_t *gap_end,
4844                                   const merge_source_t *source,
4845                                   svn_ra_session_t *ra_session,
4846                                   svn_client_ctx_t *ctx,
4847                                   apr_pool_t *scratch_pool)
4848 {
4849   svn_mergeinfo_t implicit_src_mergeinfo;
4850   svn_revnum_t old_rev = MIN(source->loc1->rev, source->loc2->rev);
4851   const svn_client__pathrev_t *primary_src
4852     = (source->loc1->rev < source->loc2->rev) ? source->loc2 : source->loc1;
4853   const char *merge_src_fspath = svn_client__pathrev_fspath(primary_src,
4854                                                             scratch_pool);
4855   svn_rangelist_t *rangelist;
4856
4857   SVN_ERR_ASSERT(source->ancestral);
4858
4859   /* Start by assuming there is no gap. */
4860   *gap_start = *gap_end = SVN_INVALID_REVNUM;
4861
4862   /* Easy out: There can't be a gap between adjacent revisions. */
4863   if (labs(source->loc1->rev - source->loc2->rev) == 1)
4864     return SVN_NO_ERROR;
4865
4866   /* Get SOURCE as mergeinfo. */
4867   SVN_ERR(svn_client__get_history_as_mergeinfo(&implicit_src_mergeinfo, NULL,
4868                                                primary_src,
4869                                                primary_src->rev, old_rev,
4870                                                ra_session,
4871                                                ctx, scratch_pool));
4872
4873   rangelist = svn_hash_gets(implicit_src_mergeinfo, merge_src_fspath);
4874
4875   if (!rangelist) /* ### Can we ever not find a rangelist? */
4876     return SVN_NO_ERROR;
4877
4878   /* A gap in natural history can result from either a copy or
4879      a rename.  If from a copy then history as mergeinfo will look
4880      something like this:
4881
4882        '/trunk:X,Y-Z'
4883
4884      If from a rename it will look like this:
4885
4886        '/trunk_old_name:X'
4887        '/trunk_new_name:Y-Z'
4888
4889     In both cases the gap, if it exists, is M-N, where M = X + 1 and
4890     N = Y - 1.
4891
4892     Note that per the rules of 'MERGEINFO MERGE SOURCE NORMALIZATION' we
4893     should never have multiple gaps, e.g. if we see anything like the
4894     following then something is quite wrong:
4895
4896         '/trunk_old_name:A,B-C'
4897         '/trunk_new_name:D-E'
4898   */
4899
4900   if (rangelist->nelts > 1) /* Copy */
4901     {
4902       const svn_merge_range_t *gap;
4903       /* As mentioned above, multiple gaps *shouldn't* be possible. */
4904       SVN_ERR_ASSERT(apr_hash_count(implicit_src_mergeinfo) == 1);
4905
4906       gap = APR_ARRAY_IDX(rangelist, rangelist->nelts - 1,
4907                           const svn_merge_range_t *);
4908
4909       *gap_start = MIN(source->loc1->rev, source->loc2->rev);
4910       *gap_end = gap->start;
4911
4912       /* ### Issue #4132:
4913          ### This assertion triggers in merge_tests.py svnmucc_abuse_1()
4914          ### when a node is replaced by an older copy of itself.
4915
4916          BH: I think we should review this and the 'rename' case to find
4917              out which behavior we really want, and if we can really
4918              determine what happened this way. */
4919       SVN_ERR_ASSERT(*gap_start < *gap_end);
4920     }
4921   else if (apr_hash_count(implicit_src_mergeinfo) > 1) /* Rename */
4922     {
4923       svn_rangelist_t *requested_rangelist =
4924         svn_rangelist__initialize(MIN(source->loc1->rev, source->loc2->rev),
4925                                   MAX(source->loc1->rev, source->loc2->rev),
4926                                   TRUE, scratch_pool);
4927       svn_rangelist_t *implicit_rangelist =
4928         apr_array_make(scratch_pool, 2, sizeof(svn_merge_range_t *));
4929       svn_rangelist_t *gap_rangelist;
4930
4931       SVN_ERR(svn_rangelist__merge_many(implicit_rangelist,
4932                                         implicit_src_mergeinfo,
4933                                         scratch_pool, scratch_pool));
4934       SVN_ERR(svn_rangelist_remove(&gap_rangelist, implicit_rangelist,
4935                                    requested_rangelist, FALSE,
4936                                    scratch_pool));
4937
4938       /* If there is anything left it is the gap. */
4939       if (gap_rangelist->nelts)
4940         {
4941           svn_merge_range_t *gap_range =
4942             APR_ARRAY_IDX(gap_rangelist, 0, svn_merge_range_t *);
4943
4944           *gap_start = gap_range->start;
4945           *gap_end = gap_range->end;
4946         }
4947     }
4948
4949   SVN_ERR_ASSERT(*gap_start == MIN(source->loc1->rev, source->loc2->rev)
4950                  || (*gap_start == SVN_INVALID_REVNUM
4951                      && *gap_end == SVN_INVALID_REVNUM));
4952   return SVN_NO_ERROR;
4953 }
4954
4955 /* Helper for do_directory_merge().
4956
4957    For each (svn_client__merge_path_t *) child in CHILDREN_WITH_MERGEINFO,
4958    populate that child's 'remaining_ranges' list with (### ... what?),
4959    and populate that child's 'implicit_mergeinfo' with its implicit
4960    mergeinfo (natural history).  CHILDREN_WITH_MERGEINFO is expected
4961    to be sorted in depth first order and each child must be processed in
4962    that order.  The inheritability of all calculated ranges is TRUE.
4963
4964    If mergeinfo is being honored (based on MERGE_B -- see HONOR_MERGEINFO()
4965    for how this is determined), this function will actually try to be
4966    intelligent about populating remaining_ranges list.  Otherwise, it
4967    will claim that each child has a single remaining range, from
4968    SOURCE->rev1, to SOURCE->rev2.
4969    ### We also take the short-cut if doing record-only.  Why?
4970
4971    SCRATCH_POOL is used for all temporary allocations.  Changes to
4972    CHILDREN_WITH_MERGEINFO are made in RESULT_POOL.
4973
4974    Note that if SOURCE->rev1 > SOURCE->rev2, then each child's remaining_ranges
4975    member does not adhere to the API rules for rangelists described in
4976    svn_mergeinfo.h -- See svn_client__merge_path_t.
4977
4978    See `MERGEINFO MERGE SOURCE NORMALIZATION' for more requirements
4979    around SOURCE.
4980 */
4981 static svn_error_t *
4982 populate_remaining_ranges(apr_array_header_t *children_with_mergeinfo,
4983                           const merge_source_t *source,
4984                           svn_ra_session_t *ra_session,
4985                           merge_cmd_baton_t *merge_b,
4986                           apr_pool_t *result_pool,
4987                           apr_pool_t *scratch_pool)
4988 {
4989   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
4990   int i;
4991   svn_revnum_t gap_start, gap_end;
4992
4993   /* If we aren't honoring mergeinfo or this is a --record-only merge,
4994      we'll make quick work of this by simply adding dummy SOURCE->rev1:rev2
4995      ranges for all children. */
4996   if (! HONOR_MERGEINFO(merge_b) || merge_b->record_only)
4997     {
4998       for (i = 0; i < children_with_mergeinfo->nelts; i++)
4999         {
5000           svn_client__merge_path_t *child =
5001             APR_ARRAY_IDX(children_with_mergeinfo, i,
5002                           svn_client__merge_path_t *);
5003
5004           svn_pool_clear(iterpool);
5005
5006           /* Issue #3646 'record-only merges create self-referential
5007              mergeinfo'.  Get the merge target's implicit mergeinfo (natural
5008              history).  We'll use it later to avoid setting self-referential
5009              mergeinfo -- see filter_natural_history_from_mergeinfo(). */
5010           if (i == 0) /* First item is always the merge target. */
5011             {
5012               SVN_ERR(get_full_mergeinfo(NULL, /* child->pre_merge_mergeinfo */
5013                                          &(child->implicit_mergeinfo),
5014                                          NULL, /* child->inherited_mergeinfo */
5015                                          svn_mergeinfo_inherited, ra_session,
5016                                          child->abspath,
5017                                          MAX(source->loc1->rev,
5018                                              source->loc2->rev),
5019                                          MIN(source->loc1->rev,
5020                                              source->loc2->rev),
5021                                          merge_b->ctx, result_pool,
5022                                          iterpool));
5023             }
5024           else
5025             {
5026               /* Issue #3443 - Subtrees of the merge target can inherit
5027                  their parent's implicit mergeinfo in most cases. */
5028               svn_client__merge_path_t *parent
5029                 = find_nearest_ancestor(children_with_mergeinfo,
5030                                         FALSE, child->abspath);
5031               svn_boolean_t child_inherits_implicit;
5032
5033               /* If CHILD is a subtree then its parent must be in
5034                  CHILDREN_WITH_MERGEINFO, see the global comment
5035                  'THE CHILDREN_WITH_MERGEINFO ARRAY'. */
5036               SVN_ERR_ASSERT(parent);
5037
5038               child_inherits_implicit = (parent && !child->switched);
5039               SVN_ERR(ensure_implicit_mergeinfo(parent, child,
5040                                                 child_inherits_implicit,
5041                                                 source->loc1->rev,
5042                                                 source->loc2->rev,
5043                                                 ra_session, merge_b->ctx,
5044                                                 result_pool, iterpool));
5045             }
5046
5047           child->remaining_ranges = svn_rangelist__initialize(source->loc1->rev,
5048                                                               source->loc2->rev,
5049                                                               TRUE,
5050                                                               result_pool);
5051         }
5052       svn_pool_destroy(iterpool);
5053       return SVN_NO_ERROR;
5054     }
5055
5056   /* If, in the merge source's history, there was a copy from an older
5057      revision, then SOURCE->loc2->url won't exist at some range M:N, where
5058      SOURCE->loc1->rev < M < N < SOURCE->loc2->rev. The rules of 'MERGEINFO
5059      MERGE SOURCE NORMALIZATION' allow this, but we must ignore these gaps
5060      when calculating what ranges remain to be merged from SOURCE. If we
5061      don't and try to merge any part of SOURCE->loc2->url@M:N we would
5062      break the editor since no part of that actually exists.  See
5063      http://svn.haxx.se/dev/archive-2008-11/0618.shtml.
5064
5065      Find the gaps in the merge target's history, if any.  Eventually
5066      we will adjust CHILD->REMAINING_RANGES such that we don't describe
5067      non-existent paths to the editor. */
5068   SVN_ERR(find_gaps_in_merge_source_history(&gap_start, &gap_end,
5069                                             source,
5070                                             ra_session, merge_b->ctx,
5071                                             iterpool));
5072
5073   /* Stash any gap in the merge command baton, we'll need it later when
5074      recording mergeinfo describing this merge. */
5075   if (SVN_IS_VALID_REVNUM(gap_start) && SVN_IS_VALID_REVNUM(gap_end))
5076     merge_b->implicit_src_gap = svn_rangelist__initialize(gap_start, gap_end,
5077                                                           TRUE, result_pool);
5078
5079   for (i = 0; i < children_with_mergeinfo->nelts; i++)
5080     {
5081       svn_client__merge_path_t *child =
5082         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
5083       const char *child_repos_path
5084         = svn_dirent_skip_ancestor(merge_b->target->abspath, child->abspath);
5085       merge_source_t child_source;
5086       svn_client__merge_path_t *parent = NULL;
5087       svn_boolean_t child_inherits_implicit;
5088
5089       svn_pool_clear(iterpool);
5090
5091       /* If the path is absent don't do subtree merge either. */
5092       SVN_ERR_ASSERT(child);
5093       if (child->absent)
5094         continue;
5095
5096       SVN_ERR_ASSERT(child_repos_path != NULL);
5097       child_source.loc1 = svn_client__pathrev_join_relpath(
5098                             source->loc1, child_repos_path, iterpool);
5099       child_source.loc2 = svn_client__pathrev_join_relpath(
5100                             source->loc2, child_repos_path, iterpool);
5101       /* ### Is the child 'ancestral' over the same revision range?  It's
5102        * not necessarily true that a child is 'ancestral' if the parent is,
5103        * nor that it's not if the parent is not.  However, here we claim
5104        * that it is.  Before we had this 'ancestral' field that we need to
5105        * set explicitly, the claim was implicit.  Either way, the impact is
5106        * that we might pass calculate_remaining_ranges() a source that is
5107        * not in fact 'ancestral' (despite its 'ancestral' field being true),
5108        * contrary to its doc-string. */
5109       child_source.ancestral = source->ancestral;
5110
5111       /* Get the explicit/inherited mergeinfo for CHILD.  If CHILD is the
5112          merge target then also get its implicit mergeinfo.  Otherwise defer
5113          this until we know it is absolutely necessary, since it requires an
5114          expensive round trip communication with the server. */
5115       SVN_ERR(get_full_mergeinfo(
5116         child->pre_merge_mergeinfo ? NULL : &(child->pre_merge_mergeinfo),
5117         /* Get implicit only for merge target. */
5118         (i == 0) ? &(child->implicit_mergeinfo) : NULL,
5119         &(child->inherited_mergeinfo),
5120         svn_mergeinfo_inherited, ra_session,
5121         child->abspath,
5122         MAX(source->loc1->rev, source->loc2->rev),
5123         MIN(source->loc1->rev, source->loc2->rev),
5124         merge_b->ctx, result_pool, iterpool));
5125
5126       /* If CHILD isn't the merge target find its parent. */
5127       if (i > 0)
5128         {
5129           parent = find_nearest_ancestor(children_with_mergeinfo,
5130                                          FALSE, child->abspath);
5131           /* If CHILD is a subtree then its parent must be in
5132              CHILDREN_WITH_MERGEINFO, see the global comment
5133              'THE CHILDREN_WITH_MERGEINFO ARRAY'. */
5134           SVN_ERR_ASSERT(parent);
5135         }
5136
5137       /* Issue #3443 - Can CHILD inherit PARENT's implicit mergeinfo, saving
5138          us from having to ask the repos?  The only time we can't do this is if
5139          CHILD is the merge target and so there is no PARENT to inherit from
5140          or if CHILD is the root of a switched subtree, in which case PARENT
5141          exists but is not CHILD's repository parent. */
5142       child_inherits_implicit = (parent && !child->switched);
5143
5144       SVN_ERR(calculate_remaining_ranges(parent, child,
5145                                          &child_source,
5146                                          child->pre_merge_mergeinfo,
5147                                          merge_b->implicit_src_gap,
5148                                          child_inherits_implicit,
5149                                          ra_session,
5150                                          merge_b->ctx, result_pool,
5151                                          iterpool));
5152
5153       /* Deal with any gap in SOURCE's natural history.
5154
5155          If the gap is a proper subset of CHILD->REMAINING_RANGES then we can
5156          safely ignore it since we won't describe this path/rev pair.
5157
5158          If the gap exactly matches or is a superset of a range in
5159          CHILD->REMAINING_RANGES then we must remove that range so we don't
5160          attempt to describe non-existent paths via the reporter, this will
5161          break the editor and our merge.
5162
5163          If the gap adjoins or overlaps a range in CHILD->REMAINING_RANGES
5164          then we must *add* the gap so we span the missing revisions. */
5165       if (child->remaining_ranges->nelts
5166           && merge_b->implicit_src_gap)
5167         {
5168           int j;
5169           svn_boolean_t proper_subset = FALSE;
5170           svn_boolean_t overlaps_or_adjoins = FALSE;
5171
5172           /* If this is a reverse merge reorder CHILD->REMAINING_RANGES
5173               so it will work with the svn_rangelist_* APIs below. */
5174           if (source->loc1->rev > source->loc2->rev)
5175             SVN_ERR(svn_rangelist_reverse(child->remaining_ranges, iterpool));
5176
5177           for (j = 0; j < child->remaining_ranges->nelts; j++)
5178             {
5179               svn_merge_range_t *range
5180                 = APR_ARRAY_IDX(child->remaining_ranges, j, svn_merge_range_t *);
5181
5182               if ((range->start <= gap_start && gap_end < range->end)
5183                   || (range->start < gap_start && gap_end <= range->end))
5184                 {
5185                   proper_subset = TRUE;
5186                   break;
5187                 }
5188               else if ((gap_start == range->start) && (range->end == gap_end))
5189                 {
5190                   break;
5191                 }
5192               else if (gap_start <= range->end && range->start <= gap_end)
5193                 /* intersect */
5194                 {
5195                   overlaps_or_adjoins = TRUE;
5196                   break;
5197                 }
5198             }
5199
5200           if (!proper_subset)
5201             {
5202               /* We need to make adjustments.  Remove from, or add the gap
5203                  to, CHILD->REMAINING_RANGES as appropriate. */
5204
5205               if (overlaps_or_adjoins)
5206                 SVN_ERR(svn_rangelist_merge2(child->remaining_ranges,
5207                                              merge_b->implicit_src_gap,
5208                                              result_pool, iterpool));
5209               else /* equals == TRUE */
5210                 SVN_ERR(svn_rangelist_remove(&(child->remaining_ranges),
5211                                              merge_b->implicit_src_gap,
5212                                              child->remaining_ranges, FALSE,
5213                                              result_pool));
5214             }
5215
5216           if (source->loc1->rev > source->loc2->rev) /* Reverse merge */
5217             SVN_ERR(svn_rangelist_reverse(child->remaining_ranges, iterpool));
5218         }
5219     }
5220
5221   svn_pool_destroy(iterpool);
5222   return SVN_NO_ERROR;
5223 }
5224
5225
5226 /*-----------------------------------------------------------------------*/
5227 \f
5228 /*** Other Helper Functions ***/
5229
5230 /* Calculate the new mergeinfo for the target tree rooted at TARGET_ABSPATH
5231    based on MERGES (a mapping of absolute WC paths to rangelists representing
5232    a merge from the source SOURCE_FSPATH).
5233
5234    If RESULT_CATALOG is NULL, then record the new mergeinfo in the WC (at,
5235    and possibly below, TARGET_ABSPATH).
5236
5237    If RESULT_CATALOG is not NULL, then don't record the new mergeinfo on the
5238    WC, but instead record it in RESULT_CATALOG, where the keys are absolute
5239    working copy paths and the values are the new mergeinfos for each.
5240    Allocate additions to RESULT_CATALOG in pool which RESULT_CATALOG was
5241    created in. */
5242 static svn_error_t *
5243 update_wc_mergeinfo(svn_mergeinfo_catalog_t result_catalog,
5244                     const char *target_abspath,
5245                     const char *source_fspath,
5246                     apr_hash_t *merges,
5247                     svn_boolean_t is_rollback,
5248                     svn_client_ctx_t *ctx,
5249                     apr_pool_t *scratch_pool)
5250 {
5251   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
5252   apr_hash_index_t *hi;
5253
5254   /* Combine the mergeinfo for the revision range just merged into
5255      the WC with its on-disk mergeinfo. */
5256   for (hi = apr_hash_first(scratch_pool, merges); hi; hi = apr_hash_next(hi))
5257     {
5258       const char *local_abspath = apr_hash_this_key(hi);
5259       svn_rangelist_t *ranges = apr_hash_this_val(hi);
5260       svn_rangelist_t *rangelist;
5261       svn_error_t *err;
5262       const char *local_abspath_rel_to_target;
5263       const char *fspath;
5264       svn_mergeinfo_t mergeinfo;
5265
5266       svn_pool_clear(iterpool);
5267
5268       /* As some of the merges may've changed the WC's mergeinfo, get
5269          a fresh copy before using it to update the WC's mergeinfo. */
5270       err = svn_client__parse_mergeinfo(&mergeinfo, ctx->wc_ctx,
5271                                         local_abspath, iterpool, iterpool);
5272
5273       /* If a directory PATH was skipped because it is missing or was
5274          obstructed by an unversioned item then there's nothing we can
5275          do with that, so skip it. */
5276       if (err)
5277         {
5278           if (err->apr_err == SVN_ERR_WC_NOT_LOCKED
5279               || err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
5280             {
5281               svn_error_clear(err);
5282               continue;
5283             }
5284           else
5285             {
5286               return svn_error_trace(err);
5287             }
5288         }
5289
5290       /* If we are attempting to set empty revision range override mergeinfo
5291          on a path with no explicit mergeinfo, we first need the
5292          mergeinfo that path inherits. */
5293       if (mergeinfo == NULL && ranges->nelts == 0)
5294         {
5295           SVN_ERR(svn_client__get_wc_mergeinfo(&mergeinfo, NULL,
5296                                                svn_mergeinfo_nearest_ancestor,
5297                                                local_abspath, NULL, NULL,
5298                                                FALSE, ctx, iterpool, iterpool));
5299         }
5300
5301       if (mergeinfo == NULL)
5302         mergeinfo = apr_hash_make(iterpool);
5303
5304       local_abspath_rel_to_target = svn_dirent_skip_ancestor(target_abspath,
5305                                                              local_abspath);
5306       SVN_ERR_ASSERT(local_abspath_rel_to_target != NULL);
5307       fspath = svn_fspath__join(source_fspath,
5308                                 local_abspath_rel_to_target,
5309                                 iterpool);
5310       rangelist = svn_hash_gets(mergeinfo, fspath);
5311       if (rangelist == NULL)
5312         rangelist = apr_array_make(iterpool, 0, sizeof(svn_merge_range_t *));
5313
5314       if (is_rollback)
5315         {
5316           ranges = svn_rangelist_dup(ranges, iterpool);
5317           SVN_ERR(svn_rangelist_reverse(ranges, iterpool));
5318           SVN_ERR(svn_rangelist_remove(&rangelist, ranges, rangelist,
5319                                        FALSE,
5320                                        iterpool));
5321         }
5322       else
5323         {
5324           SVN_ERR(svn_rangelist_merge2(rangelist, ranges, iterpool, iterpool));
5325         }
5326       /* Update the mergeinfo by adjusting the path's rangelist. */
5327       svn_hash_sets(mergeinfo, fspath, rangelist);
5328
5329       if (is_rollback && apr_hash_count(mergeinfo) == 0)
5330         mergeinfo = NULL;
5331
5332       svn_mergeinfo__remove_empty_rangelists(mergeinfo, scratch_pool);
5333
5334       if (result_catalog)
5335         {
5336           svn_mergeinfo_t existing_mergeinfo =
5337             svn_hash_gets(result_catalog, local_abspath);
5338           apr_pool_t *result_catalog_pool = apr_hash_pool_get(result_catalog);
5339
5340           if (existing_mergeinfo)
5341             SVN_ERR(svn_mergeinfo_merge2(mergeinfo, existing_mergeinfo,
5342                                          result_catalog_pool, scratch_pool));
5343           svn_hash_sets(result_catalog,
5344                         apr_pstrdup(result_catalog_pool, local_abspath),
5345                         svn_mergeinfo_dup(mergeinfo, result_catalog_pool));
5346         }
5347       else
5348         {
5349           err = svn_client__record_wc_mergeinfo(local_abspath, mergeinfo,
5350                                                 TRUE, ctx, iterpool);
5351
5352           if (err && err->apr_err == SVN_ERR_ENTRY_NOT_FOUND)
5353             {
5354               /* PATH isn't just missing, it's not even versioned as far
5355                  as this working copy knows.  But it was included in
5356                  MERGES, which means that the server knows about it.
5357                  Likely we don't have access to the source due to authz
5358                  restrictions.  For now just clear the error and
5359                  continue...
5360
5361                  ### TODO:  Set non-inheritable mergeinfo on PATH's immediate
5362                  ### parent and normal mergeinfo on PATH's siblings which we
5363                  ### do have access to. */
5364               svn_error_clear(err);
5365             }
5366           else
5367             SVN_ERR(err);
5368         }
5369     }
5370
5371   svn_pool_destroy(iterpool);
5372   return SVN_NO_ERROR;
5373 }
5374
5375 /* Helper for record_mergeinfo_for_dir_merge().
5376
5377    Record override mergeinfo on any paths skipped during a merge.
5378
5379    Set empty mergeinfo on each path in MERGE_B->SKIPPED_ABSPATHS so the path
5380    does not incorrectly inherit mergeinfo that will later be describing
5381    the merge.
5382
5383    MERGEINFO_PATH and MERGE_B are cascaded from
5384    arguments of the same name in the caller.
5385
5386    IS_ROLLBACK is true if the caller is recording a reverse merge and false
5387    otherwise.  RANGELIST is the set of revisions being merged from
5388    MERGEINFO_PATH to MERGE_B->target. */
5389 static svn_error_t *
5390 record_skips_in_mergeinfo(const char *mergeinfo_path,
5391                           const svn_rangelist_t *rangelist,
5392                           svn_boolean_t is_rollback,
5393                           merge_cmd_baton_t *merge_b,
5394                           apr_pool_t *scratch_pool)
5395 {
5396   apr_hash_index_t *hi;
5397   apr_hash_t *merges;
5398   apr_size_t nbr_skips = apr_hash_count(merge_b->skipped_abspaths);
5399   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
5400
5401   if (nbr_skips == 0)
5402     return SVN_NO_ERROR;
5403
5404   merges = apr_hash_make(scratch_pool);
5405
5406   /* Override the mergeinfo for child paths which weren't actually merged. */
5407   for (hi = apr_hash_first(scratch_pool, merge_b->skipped_abspaths); hi;
5408        hi = apr_hash_next(hi))
5409     {
5410       const char *skipped_abspath = apr_hash_this_key(hi);
5411       svn_wc_notify_state_t obstruction_state;
5412
5413       svn_pool_clear(iterpool);
5414
5415       /* Before we override, make sure this is a versioned path, it might
5416          be an external or missing from disk due to authz restrictions. */
5417       SVN_ERR(perform_obstruction_check(&obstruction_state, NULL, NULL,
5418                                         NULL, NULL,
5419                                         merge_b, skipped_abspath,
5420                                         iterpool));
5421       if (obstruction_state == svn_wc_notify_state_obstructed
5422           || obstruction_state == svn_wc_notify_state_missing)
5423         continue;
5424
5425       /* Add an empty range list for this path.
5426
5427          ### TODO: This works fine for a file path skipped because it is
5428          ### missing as long as the file's parent directory is present.
5429          ### But missing directory paths skipped are not handled yet,
5430          ### see issue #2915.
5431
5432          ### TODO: An empty range is fine if the skipped path doesn't
5433          ### inherit any mergeinfo from a parent, but if it does
5434          ### we need to account for that.  See issue #3440
5435          ### http://subversion.tigris.org/issues/show_bug.cgi?id=3440. */
5436       svn_hash_sets(merges, skipped_abspath,
5437                     apr_array_make(scratch_pool, 0,
5438                                    sizeof(svn_merge_range_t *)));
5439
5440       /* if (nbr_skips < notify_b->nbr_notifications)
5441            ### Use RANGELIST as the mergeinfo for all children of
5442            ### this path which were not also explicitly
5443            ### skipped? */
5444     }
5445   SVN_ERR(update_wc_mergeinfo(NULL, merge_b->target->abspath,
5446                               mergeinfo_path, merges,
5447                               is_rollback, merge_b->ctx, iterpool));
5448   svn_pool_destroy(iterpool);
5449   return SVN_NO_ERROR;
5450 }
5451
5452 /* Data for reporting when a merge aborted because of raising conflicts.
5453  */
5454 typedef struct single_range_conflict_report_t
5455 {
5456   /* What sub-range of the requested source raised conflicts?
5457    * The 'inheritable' flag is ignored. */
5458   merge_source_t *conflicted_range;
5459   /* What sub-range of the requested source remains to be merged?
5460    * NULL if no more.  The 'inheritable' flag is ignored. */
5461   merge_source_t *remaining_source;
5462
5463 } single_range_conflict_report_t;
5464
5465 /* Create a single_range_conflict_report_t, containing deep copies of
5466  * CONFLICTED_RANGE and REMAINING_SOURCE, allocated in RESULT_POOL. */
5467 static single_range_conflict_report_t *
5468 single_range_conflict_report_create(const merge_source_t *conflicted_range,
5469                                     const merge_source_t *remaining_source,
5470                                     apr_pool_t *result_pool)
5471 {
5472   single_range_conflict_report_t *report
5473     = apr_palloc(result_pool, sizeof(*report));
5474
5475   assert(conflicted_range != NULL);
5476
5477   report->conflicted_range = merge_source_dup(conflicted_range, result_pool);
5478   report->remaining_source
5479     = remaining_source ? merge_source_dup(remaining_source, result_pool)
5480                        : NULL;
5481   return report;
5482 }
5483
5484 /* Data for reporting when a merge aborted because of raising conflicts.
5485  *
5486  * ### TODO: More info, including the ranges (or other parameters) the user
5487  *     needs to complete the merge.
5488  */
5489 typedef struct conflict_report_t
5490 {
5491   const char *target_abspath;
5492   /* The revision range during which conflicts were raised */
5493   const merge_source_t *conflicted_range;
5494   /* Was the conflicted range the last range in the whole requested merge? */
5495   svn_boolean_t was_last_range;
5496 } conflict_report_t;
5497
5498 /* Return a new conflict_report_t containing deep copies of the parameters,
5499  * allocated in RESULT_POOL. */
5500 static conflict_report_t *
5501 conflict_report_create(const char *target_abspath,
5502                        const merge_source_t *conflicted_range,
5503                        svn_boolean_t was_last_range,
5504                        apr_pool_t *result_pool)
5505 {
5506   conflict_report_t *report = apr_palloc(result_pool, 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 conflict_report_t *
5516 conflict_report_dup(const conflict_report_t *report,
5517                     apr_pool_t *result_pool)
5518 {
5519   conflict_report_t *new = apr_pmemdup(result_pool, report, sizeof(*new));
5520
5521   new->target_abspath = apr_pstrdup(result_pool, report->target_abspath);
5522   new->conflicted_range = merge_source_dup(report->conflicted_range,
5523                                            result_pool);
5524   return new;
5525 }
5526
5527 /* Create and return an error structure appropriate for the unmerged
5528    revisions range(s). */
5529 static APR_INLINE svn_error_t *
5530 make_merge_conflict_error(conflict_report_t *report,
5531                           apr_pool_t *scratch_pool)
5532 {
5533   assert(!report || svn_dirent_is_absolute(report->target_abspath));
5534
5535   if (report && ! report->was_last_range)
5536     {
5537       svn_error_t *err = svn_error_createf(SVN_ERR_WC_FOUND_CONFLICT, NULL,
5538        _("One or more conflicts were produced while merging r%ld:%ld into\n"
5539          "'%s' --\n"
5540          "resolve all conflicts and rerun the merge to apply the remaining\n"
5541          "unmerged revisions"),
5542        report->conflicted_range->loc1->rev, report->conflicted_range->loc2->rev,
5543        svn_dirent_local_style(report->target_abspath, scratch_pool));
5544       assert(report->conflicted_range->loc1->rev != report->conflicted_range->loc2->rev); /* ### is a valid case in a 2-URL merge */
5545       return err;
5546     }
5547   return SVN_NO_ERROR;
5548 }
5549
5550 /* Helper for do_directory_merge().
5551
5552    TARGET_WCPATH is a directory and CHILDREN_WITH_MERGEINFO is filled
5553    with paths (svn_client__merge_path_t *) arranged in depth first order,
5554    which have mergeinfo set on them or meet one of the other criteria
5555    defined in get_mergeinfo_paths().  Remove any paths absent from disk
5556    or scheduled for deletion from CHILDREN_WITH_MERGEINFO which are equal to
5557    or are descendants of TARGET_WCPATH by setting those children to NULL. */
5558 static void
5559 remove_absent_children(const char *target_wcpath,
5560                        apr_array_header_t *children_with_mergeinfo)
5561 {
5562   /* Before we try to override mergeinfo for skipped paths, make sure
5563      the path isn't absent due to authz restrictions, because there's
5564      nothing we can do about those. */
5565   int i;
5566   for (i = 0; i < children_with_mergeinfo->nelts; i++)
5567     {
5568       svn_client__merge_path_t *child =
5569         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
5570       if ((child->absent || child->scheduled_for_deletion)
5571           && svn_dirent_is_ancestor(target_wcpath, child->abspath))
5572         {
5573           svn_sort__array_delete(children_with_mergeinfo, i--, 1);
5574         }
5575     }
5576 }
5577
5578 /* Helper for do_directory_merge() to handle the case where a merge editor
5579    drive removes explicit mergeinfo from a subtree of the merge target.
5580
5581    MERGE_B is cascaded from the argument of the same name in
5582    do_directory_merge().  For each path (if any) in
5583    MERGE_B->PATHS_WITH_DELETED_MERGEINFO remove that path from
5584    CHILDREN_WITH_MERGEINFO.
5585
5586    The one exception is for the merge target itself,
5587    MERGE_B->target->abspath, this must always be present in
5588    CHILDREN_WITH_MERGEINFO so this is never removed by this
5589    function. */
5590 static void
5591 remove_children_with_deleted_mergeinfo(merge_cmd_baton_t *merge_b,
5592                                        apr_array_header_t *children_with_mergeinfo)
5593 {
5594   int i;
5595
5596   if (!merge_b->paths_with_deleted_mergeinfo)
5597     return;
5598
5599   /* CHILDREN_WITH_MERGEINFO[0] is the always the merge target
5600      so start at the first child. */
5601   for (i = 1; i < children_with_mergeinfo->nelts; i++)
5602     {
5603       svn_client__merge_path_t *child =
5604         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
5605
5606       if (svn_hash_gets(merge_b->paths_with_deleted_mergeinfo, child->abspath))
5607         {
5608           svn_sort__array_delete(children_with_mergeinfo, i--, 1);
5609         }
5610     }
5611 }
5612
5613 /* Helper for do_directory_merge().
5614
5615    Set up the diff editor report to merge the SOURCE diff
5616    into TARGET_ABSPATH and drive it.
5617
5618    If mergeinfo is not being honored (based on MERGE_B -- see the doc
5619    string for HONOR_MERGEINFO() for how this is determined), then ignore
5620    CHILDREN_WITH_MERGEINFO and merge the SOURCE diff to TARGET_ABSPATH.
5621
5622    If mergeinfo is being honored then perform a history-aware merge,
5623    describing TARGET_ABSPATH and its subtrees to the reporter in such as way
5624    as to avoid repeating merges already performed per the mergeinfo and
5625    natural history of TARGET_ABSPATH and its subtrees.
5626
5627    The ranges that still need to be merged to the TARGET_ABSPATH and its
5628    subtrees are described in CHILDREN_WITH_MERGEINFO, an array of
5629    svn_client__merge_path_t * -- see 'THE CHILDREN_WITH_MERGEINFO ARRAY'
5630    comment at the top of this file for more info.  Note that it is possible
5631    TARGET_ABSPATH and/or some of its subtrees need only a subset, or no part,
5632    of SOURCE to be merged.  Though there is little point to
5633    calling this function if TARGET_ABSPATH and all its subtrees have already
5634    had SOURCE merged, this will work but is a no-op.
5635
5636    SOURCE->rev1 and SOURCE->rev2 must be bound by the set of remaining_ranges
5637    fields in CHILDREN_WITH_MERGEINFO's elements, specifically:
5638
5639    For forward merges (SOURCE->rev1 < SOURCE->rev2):
5640
5641      1) The first svn_merge_range_t * element of each child's remaining_ranges
5642         array must meet one of the following conditions:
5643
5644         a) The range's start field is greater than or equal to SOURCE->rev2.
5645
5646         b) The range's end field is SOURCE->rev2.
5647
5648      2) Among all the ranges that meet condition 'b' the oldest start
5649         revision must equal SOURCE->rev1.
5650
5651    For reverse merges (SOURCE->rev1 > SOURCE->rev2):
5652
5653      1) The first svn_merge_range_t * element of each child's remaining_ranges
5654         array must meet one of the following conditions:
5655
5656         a) The range's start field is less than or equal to SOURCE->rev2.
5657
5658         b) The range's end field is SOURCE->rev2.
5659
5660      2) Among all the ranges that meet condition 'b' the youngest start
5661         revision must equal SOURCE->rev1.
5662
5663    Note: If the first svn_merge_range_t * element of some subtree child's
5664    remaining_ranges array is the same as the first range of that child's
5665    nearest path-wise ancestor, then the subtree child *will not* be described
5666    to the reporter.
5667
5668    DEPTH, NOTIFY_B, and MERGE_B are cascaded from do_directory_merge(), see
5669    that function for more info.
5670
5671    MERGE_B->ra_session1 and MERGE_B->ra_session2 are RA sessions open to any
5672    URL in the repository of SOURCE; they may be temporarily reparented within
5673    this function.
5674
5675    If SOURCE->ancestral is set, then SOURCE->loc1 must be a
5676    historical ancestor of SOURCE->loc2, or vice-versa (see
5677    `MERGEINFO MERGE SOURCE NORMALIZATION' for more requirements around
5678    SOURCE in this case).
5679 */
5680 static svn_error_t *
5681 drive_merge_report_editor(const char *target_abspath,
5682                           const merge_source_t *source,
5683                           const apr_array_header_t *children_with_mergeinfo,
5684                           const svn_diff_tree_processor_t *processor,
5685                           svn_depth_t depth,
5686                           merge_cmd_baton_t *merge_b,
5687                           apr_pool_t *scratch_pool)
5688 {
5689   const svn_ra_reporter3_t *reporter;
5690   const svn_delta_editor_t *diff_editor;
5691   void *diff_edit_baton;
5692   void *report_baton;
5693   svn_revnum_t target_start;
5694   svn_boolean_t honor_mergeinfo = HONOR_MERGEINFO(merge_b);
5695   const char *old_sess1_url, *old_sess2_url;
5696   svn_boolean_t is_rollback = source->loc1->rev > source->loc2->rev;
5697
5698   /* Start with a safe default starting revision for the editor and the
5699      merge target. */
5700   target_start = source->loc1->rev;
5701
5702   /* If we are honoring mergeinfo the starting revision for the merge target
5703      might not be SOURCE->rev1, in fact the merge target might not need *any*
5704      part of SOURCE merged -- Instead some subtree of the target
5705      needs SOURCE -- So get the right starting revision for the
5706      target. */
5707   if (honor_mergeinfo)
5708     {
5709       svn_client__merge_path_t *child;
5710
5711       /* CHILDREN_WITH_MERGEINFO must always exist if we are honoring
5712          mergeinfo and must have at least one element (describing the
5713          merge target). */
5714       SVN_ERR_ASSERT(children_with_mergeinfo);
5715       SVN_ERR_ASSERT(children_with_mergeinfo->nelts);
5716
5717       /* Get the merge target's svn_client__merge_path_t, which is always
5718          the first in the array due to depth first sorting requirement,
5719          see 'THE CHILDREN_WITH_MERGEINFO ARRAY'. */
5720       child = APR_ARRAY_IDX(children_with_mergeinfo, 0,
5721                             svn_client__merge_path_t *);
5722       SVN_ERR_ASSERT(child);
5723       if (child->remaining_ranges->nelts == 0)
5724         {
5725           /* The merge target doesn't need anything merged. */
5726           target_start = source->loc2->rev;
5727         }
5728       else
5729         {
5730           /* The merge target has remaining revisions to merge.  These
5731              ranges may fully or partially overlap the range described
5732              by SOURCE->rev1:rev2 or may not intersect that range at
5733              all. */
5734           svn_merge_range_t *range =
5735             APR_ARRAY_IDX(child->remaining_ranges, 0,
5736                           svn_merge_range_t *);
5737           if ((!is_rollback && range->start > source->loc2->rev)
5738               || (is_rollback && range->start < source->loc2->rev))
5739             {
5740               /* Merge target's first remaining range doesn't intersect. */
5741               target_start = source->loc2->rev;
5742             }
5743           else
5744             {
5745               /* Merge target's first remaining range partially or
5746                  fully overlaps. */
5747               target_start = range->start;
5748             }
5749         }
5750     }
5751
5752   SVN_ERR(svn_client__ensure_ra_session_url(&old_sess1_url,
5753                                             merge_b->ra_session1,
5754                                             source->loc1->url, scratch_pool));
5755   /* Temporarily point our second RA session to SOURCE->loc1->url, too.  We use
5756      this to request individual file contents. */
5757   SVN_ERR(svn_client__ensure_ra_session_url(&old_sess2_url,
5758                                             merge_b->ra_session2,
5759                                             source->loc1->url, scratch_pool));
5760
5761   /* Get the diff editor and a reporter with which to, ultimately,
5762      drive it. */
5763   SVN_ERR(svn_client__get_diff_editor2(&diff_editor, &diff_edit_baton,
5764                                        merge_b->ra_session2,
5765                                        depth,
5766                                        source->loc1->rev,
5767                                        TRUE /* text_deltas */,
5768                                        processor,
5769                                        merge_b->ctx->cancel_func,
5770                                        merge_b->ctx->cancel_baton,
5771                                        scratch_pool));
5772   SVN_ERR(svn_ra_do_diff3(merge_b->ra_session1,
5773                           &reporter, &report_baton, source->loc2->rev,
5774                           "", depth, merge_b->diff_ignore_ancestry,
5775                           TRUE,  /* text_deltas */
5776                           source->loc2->url, diff_editor, diff_edit_baton,
5777                           scratch_pool));
5778
5779   /* Drive the reporter. */
5780   SVN_ERR(reporter->set_path(report_baton, "", target_start, depth,
5781                              FALSE, NULL, scratch_pool));
5782   if (honor_mergeinfo && children_with_mergeinfo)
5783     {
5784       /* Describe children with mergeinfo overlapping this merge
5785          operation such that no repeated diff is retrieved for them from
5786          the repository. */
5787       int i;
5788       apr_pool_t *iterpool = svn_pool_create(scratch_pool);
5789
5790       /* Start with CHILDREN_WITH_MERGEINFO[1], CHILDREN_WITH_MERGEINFO[0]
5791          is always the merge target (TARGET_ABSPATH). */
5792       for (i = 1; i < children_with_mergeinfo->nelts; i++)
5793         {
5794           svn_merge_range_t *range;
5795           const char *child_repos_path;
5796           const svn_client__merge_path_t *parent;
5797           const svn_client__merge_path_t *child =
5798             APR_ARRAY_IDX(children_with_mergeinfo, i,
5799                           svn_client__merge_path_t *);
5800
5801           SVN_ERR_ASSERT(child);
5802           if (child->absent)
5803             continue;
5804
5805           svn_pool_clear(iterpool);
5806
5807           /* Find this child's nearest wc ancestor with mergeinfo. */
5808           parent = find_nearest_ancestor(children_with_mergeinfo,
5809                                          FALSE, child->abspath);
5810
5811           /* If a subtree needs the same range applied as its nearest parent
5812              with mergeinfo or neither the subtree nor this parent need
5813              SOURCE->rev1:rev2 merged, then we don't need to describe the
5814              subtree separately.  In the latter case this could break the
5815              editor if child->abspath didn't exist at SOURCE->rev2 and we
5816              attempt to describe it via a reporter set_path call. */
5817           if (child->remaining_ranges->nelts)
5818             {
5819               range = APR_ARRAY_IDX(child->remaining_ranges, 0,
5820                                     svn_merge_range_t *);
5821               if ((!is_rollback && range->start > source->loc2->rev)
5822                   || (is_rollback && range->start < source->loc2->rev))
5823                 {
5824                   /* This child's first remaining range comes after the range
5825                      we are currently merging, so skip it. We expect to get
5826                      to it in a subsequent call to this function. */
5827                   continue;
5828                 }
5829               else if (parent->remaining_ranges->nelts)
5830                 {
5831                    svn_merge_range_t *parent_range =
5832                     APR_ARRAY_IDX(parent->remaining_ranges, 0,
5833                                   svn_merge_range_t *);
5834                    svn_merge_range_t *child_range =
5835                     APR_ARRAY_IDX(child->remaining_ranges, 0,
5836                                   svn_merge_range_t *);
5837                   if (parent_range->start == child_range->start)
5838                     continue; /* Subtree needs same range as parent. */
5839                 }
5840             }
5841           else /* child->remaining_ranges->nelts == 0*/
5842             {
5843               /* If both the subtree and its parent need no ranges applied
5844                  consider that as the "same ranges" and don't describe
5845                  the subtree. */
5846               if (parent->remaining_ranges->nelts == 0)
5847                 continue;
5848             }
5849
5850           /* Ok, we really need to describe this subtree as it needs different
5851              ranges applied than its nearest working copy parent. */
5852           child_repos_path = svn_dirent_is_child(target_abspath,
5853                                                  child->abspath,
5854                                                  iterpool);
5855           /* This loop is only processing subtrees, so CHILD->ABSPATH
5856              better be a proper child of the merge target. */
5857           SVN_ERR_ASSERT(child_repos_path);
5858
5859           if ((child->remaining_ranges->nelts == 0)
5860               || (is_rollback && (range->start < source->loc2->rev))
5861               || (!is_rollback && (range->start > source->loc2->rev)))
5862             {
5863               /* Nothing to merge to this child.  We'll claim we have
5864                  it up to date so the server doesn't send us
5865                  anything. */
5866               SVN_ERR(reporter->set_path(report_baton, child_repos_path,
5867                                          source->loc2->rev, depth, FALSE,
5868                                          NULL, iterpool));
5869             }
5870           else
5871             {
5872               SVN_ERR(reporter->set_path(report_baton, child_repos_path,
5873                                          range->start, depth, FALSE,
5874                                          NULL, iterpool));
5875             }
5876         }
5877       svn_pool_destroy(iterpool);
5878     }
5879   SVN_ERR(reporter->finish_report(report_baton, scratch_pool));
5880
5881   /* Point the merge baton's RA sessions back where they were. */
5882   SVN_ERR(svn_ra_reparent(merge_b->ra_session1, old_sess1_url, scratch_pool));
5883   SVN_ERR(svn_ra_reparent(merge_b->ra_session2, old_sess2_url, scratch_pool));
5884
5885   return SVN_NO_ERROR;
5886 }
5887
5888 /* Iterate over each svn_client__merge_path_t * element in
5889    CHILDREN_WITH_MERGEINFO and, if START_REV is true, find the most inclusive
5890    start revision among those element's first remaining_ranges element.  If
5891    START_REV is false, then look for the most inclusive end revision.
5892
5893    If IS_ROLLBACK is true the youngest start or end (as per START_REV)
5894    revision is considered the "most inclusive" otherwise the oldest revision
5895    is.
5896
5897    If none of CHILDREN_WITH_MERGEINFO's elements have any remaining ranges
5898    return SVN_INVALID_REVNUM. */
5899 static svn_revnum_t
5900 get_most_inclusive_rev(const apr_array_header_t *children_with_mergeinfo,
5901                        svn_boolean_t is_rollback,
5902                        svn_boolean_t start_rev)
5903 {
5904   int i;
5905   svn_revnum_t most_inclusive_rev = SVN_INVALID_REVNUM;
5906
5907   for (i = 0; i < children_with_mergeinfo->nelts; i++)
5908     {
5909       svn_client__merge_path_t *child =
5910         APR_ARRAY_IDX(children_with_mergeinfo, i, svn_client__merge_path_t *);
5911
5912       if ((! child) || child->absent)
5913         continue;
5914       if (child->remaining_ranges->nelts > 0)
5915         {
5916           svn_merge_range_t *range =
5917             APR_ARRAY_IDX(child->remaining_ranges, 0, svn_merge_range_t *);
5918
5919           /* Are we looking for the most inclusive start or end rev? */
5920           svn_revnum_t rev = start_rev ? range->start : range->end;
5921
5922           if ((most_inclusive_rev == SVN_INVALID_REVNUM)
5923               || (is_rollback && (rev > most_inclusive_rev))
5924               || ((! is_rollback) && (rev < most_inclusive_rev)))
5925             most_inclusive_rev = rev;
5926         }
5927     }
5928   return most_inclusive_rev;
5929 }
5930
5931
5932 /* If first item in each child of CHILDREN_WITH_MERGEINFO's
5933    remaining_ranges is inclusive of END_REV, Slice the first range in
5934    to two at END_REV. All the allocations are persistent and allocated
5935    from POOL. */
5936 static void
5937 slice_remaining_ranges(apr_array_header_t *children_with_mergeinfo,
5938                        svn_boolean_t is_rollback, svn_revnum_t end_rev,
5939                        apr_pool_t *pool)
5940 {
5941   int i;
5942   for (i = 0; i < children_with_mergeinfo->nelts; i++)
5943     {
5944       svn_client__merge_path_t *child =
5945                                      APR_ARRAY_IDX(children_with_mergeinfo, i,
5946                                                    svn_client__merge_path_t *);
5947       if (!child || child->absent)
5948         continue;
5949       if (child->remaining_ranges->nelts > 0)
5950         {
5951           svn_merge_range_t *range = APR_ARRAY_IDX(child->remaining_ranges, 0,
5952                                                    svn_merge_range_t *);
5953           if ((is_rollback && (range->start > end_rev)
5954                && (range->end < end_rev))
5955               || (!is_rollback && (range->start < end_rev)
5956                   && (range->end > end_rev)))
5957             {
5958               svn_merge_range_t *split_range1, *split_range2;
5959
5960               split_range1 = svn_merge_range_dup(range, pool);
5961               split_range2 = svn_merge_range_dup(range, pool);
5962               split_range1->end = end_rev;
5963               split_range2->start = end_rev;
5964               APR_ARRAY_IDX(child->remaining_ranges, 0,
5965                             svn_merge_range_t *) = split_range1;
5966               svn_sort__array_insert(child->remaining_ranges, &split_range2, 1);
5967             }
5968         }
5969     }
5970 }
5971
5972 /* Helper for do_directory_merge().
5973
5974    For each child in CHILDREN_WITH_MERGEINFO remove the first remaining_ranges
5975    svn_merge_range_t *element of the child if that range has an end revision
5976    equal to REVISION.
5977
5978    If a range is removed from a child's remaining_ranges array, allocate the
5979    new remaining_ranges array in POOL.
5980  */
5981 static void
5982 remove_first_range_from_remaining_ranges(svn_revnum_t revision,
5983                                          apr_array_header_t
5984                                            *children_with_mergeinfo,
5985                                          apr_pool_t *pool)
5986 {
5987   int i;
5988
5989   for (i = 0; i < children_with_mergeinfo->nelts; i++)
5990     {
5991       svn_client__merge_path_t *child =
5992                                 APR_ARRAY_IDX(children_with_mergeinfo, i,
5993                                               svn_client__merge_path_t *);
5994       if (!child || child->absent)
5995         continue;
5996       if (child->remaining_ranges->nelts > 0)
5997         {
5998           svn_merge_range_t *first_range =
5999             APR_ARRAY_IDX(child->remaining_ranges, 0, svn_merge_range_t *);
6000           if (first_range->end == revision)
6001             {
6002               svn_sort__array_delete(child->remaining_ranges, 0, 1);
6003             }
6004         }
6005     }
6006 }
6007
6008 /* Get a file's content and properties from the repository.
6009    Set *FILENAME to the local path to a new temporary file holding its text,
6010    and set *PROPS to a new hash of its properties.
6011
6012    RA_SESSION is a session open to the correct repository, which will be
6013    temporarily reparented to the URL of the file itself.  LOCATION is the
6014    repository location of the file.
6015
6016    The resulting file and the return values live as long as RESULT_POOL, all
6017    other allocations occur in SCRATCH_POOL.
6018 */
6019 static svn_error_t *
6020 single_file_merge_get_file(const char **filename,
6021                            apr_hash_t **props,
6022                            svn_ra_session_t *ra_session,
6023                            const svn_client__pathrev_t *location,
6024                            const char *wc_target,
6025                            apr_pool_t *result_pool,
6026                            apr_pool_t *scratch_pool)
6027 {
6028   svn_stream_t *stream;
6029   const char *old_sess_url;
6030   svn_error_t *err;
6031
6032   SVN_ERR(svn_stream_open_unique(&stream, filename, NULL,
6033                                  svn_io_file_del_on_pool_cleanup,
6034                                  result_pool, scratch_pool));
6035
6036   SVN_ERR(svn_client__ensure_ra_session_url(&old_sess_url, ra_session, location->url,
6037                                             scratch_pool));
6038   err = svn_ra_get_file(ra_session, "", location->rev,
6039                         stream, NULL, props, scratch_pool);
6040   SVN_ERR(svn_error_compose_create(
6041             err, svn_ra_reparent(ra_session, old_sess_url, scratch_pool)));
6042
6043   return svn_error_trace(svn_stream_close(stream));
6044 }
6045
6046 /* Compare two svn_client__merge_path_t elements **A and **B, given the
6047    addresses of pointers to them. Return an integer less than, equal to, or
6048    greater than zero if A sorts before, the same as, or after B, respectively.
6049    This is a helper for qsort() and bsearch() on an array of such elements. */
6050 static int
6051 compare_merge_path_t_as_paths(const void *a,
6052                               const void *b)
6053 {
6054   const svn_client__merge_path_t *child1
6055     = *((const svn_client__merge_path_t * const *) a);
6056   const svn_client__merge_path_t *child2
6057     = *((const svn_client__merge_path_t * const *) b);
6058
6059   return svn_path_compare_paths(child1->abspath, child2->abspath);
6060 }
6061
6062 /* Return a pointer to the element of CHILDREN_WITH_MERGEINFO whose path
6063  * is PATH, or return NULL if there is no such element. */
6064 static svn_client__merge_path_t *
6065 get_child_with_mergeinfo(const apr_array_header_t *children_with_mergeinfo,
6066                          const char *abspath)
6067 {
6068   svn_client__merge_path_t merge_path;
6069   svn_client__merge_path_t *key;
6070   svn_client__merge_path_t **pchild;
6071
6072   merge_path.abspath = abspath;
6073   key = &merge_path;
6074   pchild = bsearch(&key, children_with_mergeinfo->elts,
6075                    children_with_mergeinfo->nelts,
6076                    children_with_mergeinfo->elt_size,
6077                    compare_merge_path_t_as_paths);
6078   return pchild ? *pchild : NULL;
6079 }
6080
6081 /* Insert a deep copy of INSERT_ELEMENT into the CHILDREN_WITH_MERGEINFO
6082    array at its correct position.  Allocate the new storage in POOL.
6083    CHILDREN_WITH_MERGEINFO is a depth first sorted array of
6084    (svn_client__merge_path_t *).
6085
6086    ### Most callers don't need this to deep-copy the new element.
6087    ### It may be more efficient for some callers to insert a bunch of items
6088        out of order and then sort afterwards. (One caller is doing a qsort
6089        after calling this anyway.)
6090  */
6091 static void
6092 insert_child_to_merge(apr_array_header_t *children_with_mergeinfo,
6093                       const svn_client__merge_path_t *insert_element,
6094                       apr_pool_t *pool)
6095 {
6096   int insert_index;
6097   const svn_client__merge_path_t *new_element;
6098
6099   /* Find where to insert the new element */
6100   insert_index =
6101     svn_sort__bsearch_lower_bound(children_with_mergeinfo, &insert_element,
6102                                   compare_merge_path_t_as_paths);
6103
6104   new_element = svn_client__merge_path_dup(insert_element, pool);
6105   svn_sort__array_insert(children_with_mergeinfo, &new_element, insert_index);
6106 }
6107
6108 /* Helper for get_mergeinfo_paths().
6109
6110    CHILDREN_WITH_MERGEINFO, DEPTH, and POOL are
6111    all cascaded from the arguments of the same name to get_mergeinfo_paths().
6112
6113    TARGET is the merge target.
6114
6115    *CHILD is the element in in CHILDREN_WITH_MERGEINFO that
6116    get_mergeinfo_paths() is iterating over and *CURR_INDEX is index for
6117    *CHILD.
6118
6119    If CHILD->ABSPATH is equal to MERGE_CMD_BATON->target->abspath do nothing.
6120    Else if CHILD->ABSPATH is switched or absent then make sure its immediate
6121    (as opposed to nearest) parent in CHILDREN_WITH_MERGEINFO is marked as
6122    missing a child.  If the immediate parent does not exist in
6123    CHILDREN_WITH_MERGEINFO then create it (and increment *CURR_INDEX so that
6124    caller doesn't process the inserted element).  Also ensure that
6125    CHILD->ABSPATH's siblings which are not already present in
6126    CHILDREN_WITH_MERGEINFO are also added to the array, limited by DEPTH
6127    (e.g. don't add directory siblings of a switched file).
6128    Use POOL for temporary allocations only, any new CHILDREN_WITH_MERGEINFO
6129    elements are allocated in POOL. */
6130 static svn_error_t *
6131 insert_parent_and_sibs_of_sw_absent_del_subtree(
6132                                    apr_array_header_t *children_with_mergeinfo,
6133                                    const merge_target_t *target,
6134                                    int *curr_index,
6135                                    svn_client__merge_path_t *child,
6136                                    svn_depth_t depth,
6137                                    svn_client_ctx_t *ctx,
6138                                    apr_pool_t *pool)
6139 {
6140   svn_client__merge_path_t *parent;
6141   const char *parent_abspath;
6142   apr_pool_t *iterpool;
6143   const apr_array_header_t *children;
6144   int i;
6145
6146   if (!(child->absent
6147           || (child->switched
6148               && strcmp(target->abspath,
6149                         child->abspath) != 0)))
6150     return SVN_NO_ERROR;
6151
6152   parent_abspath = svn_dirent_dirname(child->abspath, pool);
6153   parent = get_child_with_mergeinfo(children_with_mergeinfo, parent_abspath);
6154   if (parent)
6155     {
6156       parent->missing_child = child->absent;
6157       parent->switched_child = child->switched;
6158     }
6159   else
6160     {
6161       /* Create a new element to insert into CHILDREN_WITH_MERGEINFO. */
6162       parent = svn_client__merge_path_create(parent_abspath, pool);
6163       parent->missing_child = child->absent;
6164       parent->switched_child = child->switched;
6165       /* Insert PARENT into CHILDREN_WITH_MERGEINFO. */
6166       insert_child_to_merge(children_with_mergeinfo, parent, pool);
6167       /* Increment for loop index so we don't process the inserted element. */
6168       (*curr_index)++;
6169     } /*(parent == NULL) */
6170
6171   /* Add all of PARENT's non-missing children that are not already present.*/
6172   SVN_ERR(svn_wc__node_get_children_of_working_node(&children, ctx->wc_ctx,
6173                                                     parent_abspath,
6174                                                     pool, pool));
6175   iterpool = svn_pool_create(pool);
6176   for (i = 0; i < children->nelts; i++)
6177     {
6178       const char *child_abspath = APR_ARRAY_IDX(children, i, const char *);
6179       svn_client__merge_path_t *sibling_of_missing;
6180
6181       svn_pool_clear(iterpool);
6182
6183       /* Does this child already exist in CHILDREN_WITH_MERGEINFO? */
6184       sibling_of_missing = get_child_with_mergeinfo(children_with_mergeinfo,
6185                                                     child_abspath);
6186       /* Create the missing child and insert it into CHILDREN_WITH_MERGEINFO.*/
6187       if (!sibling_of_missing)
6188         {
6189           /* Don't add directory children if DEPTH is svn_depth_files. */
6190           if (depth == svn_depth_files)
6191             {
6192               svn_node_kind_t child_kind;
6193
6194               SVN_ERR(svn_wc_read_kind2(&child_kind,
6195                                         ctx->wc_ctx, child_abspath,
6196                                         FALSE, FALSE, iterpool));
6197               if (child_kind != svn_node_file)
6198                 continue;
6199             }
6200
6201           sibling_of_missing = svn_client__merge_path_create(child_abspath,
6202                                                              pool);
6203           insert_child_to_merge(children_with_mergeinfo, sibling_of_missing,
6204                                 pool);
6205         }
6206     }
6207
6208   svn_pool_destroy(iterpool);
6209
6210   return SVN_NO_ERROR;
6211 }
6212
6213 /* pre_merge_status_cb's baton */
6214 struct pre_merge_status_baton_t
6215 {
6216   svn_wc_context_t *wc_ctx;
6217
6218   /* const char *absolute_wc_path to svn_depth_t * mapping for depths
6219      of empty, immediates, and files. */
6220   apr_hash_t *shallow_subtrees;
6221
6222   /* const char *absolute_wc_path to the same, for all paths missing
6223      from the working copy. */
6224   apr_hash_t *missing_subtrees;
6225
6226   /* const char *absolute_wc_path const char * repos relative path, describing
6227      the root of each switched subtree in the working copy and the repository
6228      relative path it is switched to. */
6229   apr_hash_t *switched_subtrees;
6230
6231   /* A pool to allocate additions to the above hashes in. */
6232   apr_pool_t *pool;
6233 };
6234
6235 /* A svn_wc_status_func4_t callback used by get_mergeinfo_paths to gather
6236    all switched, depth filtered and missing subtrees under a merge target.
6237
6238    Note that this doesn't see server and user excluded trees. */
6239 static svn_error_t *
6240 pre_merge_status_cb(void *baton,
6241                     const char *local_abspath,
6242                     const svn_wc_status3_t *status,
6243                     apr_pool_t *scratch_pool)
6244 {
6245   struct pre_merge_status_baton_t *pmsb = baton;
6246
6247   if (status->switched && !status->file_external)
6248     {
6249       store_path(pmsb->switched_subtrees, local_abspath);
6250     }
6251
6252   if (status->depth == svn_depth_empty
6253       || status->depth == svn_depth_files)
6254     {
6255       const char *dup_abspath;
6256       svn_depth_t *depth = apr_pmemdup(pmsb->pool, &status->depth,
6257                                        sizeof *depth);
6258
6259       dup_abspath = apr_pstrdup(pmsb->pool, local_abspath);
6260
6261       svn_hash_sets(pmsb->shallow_subtrees, dup_abspath, depth);
6262     }
6263
6264   if (status->node_status == svn_wc_status_missing)
6265     {
6266       svn_boolean_t new_missing_root = TRUE;
6267       apr_hash_index_t *hi;
6268
6269       for (hi = apr_hash_first(scratch_pool, pmsb->missing_subtrees);
6270            hi;
6271            hi = apr_hash_next(hi))
6272         {
6273           const char *missing_root_path = apr_hash_this_key(hi);
6274
6275           if (svn_dirent_is_ancestor(missing_root_path,
6276                                      local_abspath))
6277             {
6278               new_missing_root = FALSE;
6279               break;
6280             }
6281         }
6282
6283       if (new_missing_root)
6284         store_path(pmsb->missing_subtrees, local_abspath);
6285     }
6286
6287   return SVN_NO_ERROR;
6288 }
6289
6290 /* Find all the subtrees in the working copy tree rooted at TARGET_ABSPATH
6291  * that have explicit mergeinfo.
6292  * Set *SUBTREES_WITH_MERGEINFO to a hash mapping (const char *) absolute
6293  * WC path to (svn_mergeinfo_t *) mergeinfo.
6294  *
6295  * ### Is this function equivalent to:
6296  *
6297  *   svn_client__get_wc_mergeinfo_catalog(
6298  *     subtrees_with_mergeinfo, inherited=NULL, include_descendants=TRUE,
6299  *     svn_mergeinfo_explicit, target_abspath, limit_path=NULL,
6300  *     walked_path=NULL, ignore_invalid_mergeinfo=FALSE, ...)
6301  *
6302  *   except for the catalog keys being abspaths instead of repo-relpaths?
6303  */
6304 static svn_error_t *
6305 get_wc_explicit_mergeinfo_catalog(apr_hash_t **subtrees_with_mergeinfo,
6306                                   const char *target_abspath,
6307                                   svn_depth_t depth,
6308                                   svn_client_ctx_t *ctx,
6309                                   apr_pool_t *result_pool,
6310                                   apr_pool_t *scratch_pool)
6311 {
6312   svn_opt_revision_t working_revision = { svn_opt_revision_working, { 0 } };
6313   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
6314   apr_hash_index_t *hi;
6315   apr_hash_t *externals;
6316
6317   SVN_ERR(svn_client_propget5(subtrees_with_mergeinfo, NULL,
6318                               SVN_PROP_MERGEINFO, target_abspath,
6319                               &working_revision, &working_revision, NULL,
6320                               depth, NULL, ctx, result_pool, scratch_pool));
6321
6322   SVN_ERR(svn_wc__externals_defined_below(&externals, ctx->wc_ctx,
6323                                           target_abspath, scratch_pool,
6324                                           scratch_pool));
6325
6326   /* Convert property values to svn_mergeinfo_t. */
6327   for (hi = apr_hash_first(scratch_pool, *subtrees_with_mergeinfo);
6328        hi;
6329        hi = apr_hash_next(hi))
6330     {
6331       const char *wc_path = apr_hash_this_key(hi);
6332       svn_string_t *mergeinfo_string = apr_hash_this_val(hi);
6333       svn_mergeinfo_t mergeinfo;
6334       svn_error_t *err;
6335
6336       /* svn_client_propget5 picks up file externals with
6337          mergeinfo, but we don't want those. */
6338       if (svn_hash_gets(externals, wc_path))
6339         {
6340           svn_hash_sets(*subtrees_with_mergeinfo, wc_path, NULL);
6341           continue;
6342         }
6343
6344       svn_pool_clear(iterpool);
6345
6346       err = svn_mergeinfo_parse(&mergeinfo, mergeinfo_string->data,
6347                                 result_pool);
6348       if (err)
6349         {
6350           if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
6351             {
6352               err = svn_error_createf(
6353                 SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING, err,
6354                 _("Invalid mergeinfo detected on '%s', "
6355                   "merge tracking not possible"),
6356                 svn_dirent_local_style(wc_path, scratch_pool));
6357             }
6358           return svn_error_trace(err);
6359         }
6360       svn_hash_sets(*subtrees_with_mergeinfo, wc_path, mergeinfo);
6361     }
6362   svn_pool_destroy(iterpool);
6363
6364   return SVN_NO_ERROR;
6365 }
6366
6367 /* Helper for do_directory_merge() when performing merge-tracking aware
6368    merges.
6369
6370    Walk of the working copy tree rooted at TARGET->abspath to
6371    depth DEPTH.  Create an svn_client__merge_path_t * for any path which meets
6372    one or more of the following criteria:
6373
6374      1) Path has working svn:mergeinfo.
6375      2) Path is switched.
6376      3) Path is a subtree of the merge target (i.e. is not equal to
6377         TARGET->abspath) and has no mergeinfo of its own but
6378         its immediate parent has mergeinfo with non-inheritable ranges.  If
6379         this isn't a dry-run and the merge is between differences in the same
6380         repository, then this function will set working mergeinfo on the path
6381         equal to the mergeinfo inheritable from its parent.
6382      4) Path has an immediate child (or children) missing from the WC because
6383         the child is switched or absent from the WC, or due to a sparse
6384         checkout.
6385      5) Path has a sibling (or siblings) missing from the WC because the
6386         sibling is switched, absent, scheduled for deletion, or missing due to
6387         a sparse checkout.
6388      6) Path is absent from disk due to an authz restriction.
6389      7) Path is equal to TARGET->abspath.
6390      8) Path is an immediate *directory* child of
6391         TARGET->abspath and DEPTH is svn_depth_immediates.
6392      9) Path is an immediate *file* child of TARGET->abspath
6393         and DEPTH is svn_depth_files.
6394      10) Path is at a depth of 'empty' or 'files'.
6395      11) Path is missing from disk (e.g. due to an OS-level deletion).
6396
6397    If subtrees within the requested DEPTH are unexpectedly missing disk,
6398    then raise SVN_ERR_CLIENT_NOT_READY_TO_MERGE.
6399
6400    Store the svn_client__merge_path_t *'s in *CHILDREN_WITH_MERGEINFO in
6401    depth-first order based on the svn_client__merge_path_t *s path member as
6402    sorted by svn_path_compare_paths().  Set the remaining_ranges field of each
6403    element to NULL.
6404
6405    Note: Since the walk is rooted at TARGET->abspath, the
6406    latter is guaranteed to be in *CHILDREN_WITH_MERGEINFO and due to the
6407    depth-first ordering it is guaranteed to be the first element in
6408    *CHILDREN_WITH_MERGEINFO.
6409
6410    MERGE_CMD_BATON is cascaded from the argument of the same name in
6411    do_directory_merge().
6412 */
6413 static svn_error_t *
6414 get_mergeinfo_paths(apr_array_header_t *children_with_mergeinfo,
6415                     const merge_target_t *target,
6416                     svn_depth_t depth,
6417                     svn_boolean_t dry_run,
6418                     svn_boolean_t same_repos,
6419                     svn_client_ctx_t *ctx,
6420                     apr_pool_t *result_pool,
6421                     apr_pool_t *scratch_pool)
6422 {
6423   int i;
6424   apr_pool_t *iterpool = svn_pool_create(scratch_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   SVN_ERR(get_wc_explicit_mergeinfo_catalog(&subtrees_with_mergeinfo,
6434                                             target->abspath,
6435                                             depth, ctx,
6436                                             result_pool, scratch_pool));
6437   if (subtrees_with_mergeinfo)
6438     {
6439       apr_hash_index_t *hi;
6440
6441       for (hi = apr_hash_first(scratch_pool, subtrees_with_mergeinfo);
6442            hi;
6443            hi = apr_hash_next(hi))
6444         {
6445           const char *wc_path = apr_hash_this_key(hi);
6446           svn_mergeinfo_t mergeinfo = apr_hash_this_val(hi);
6447           svn_client__merge_path_t *mergeinfo_child =
6448             svn_client__merge_path_create(wc_path, result_pool);
6449
6450           svn_pool_clear(iterpool);
6451
6452           /* Stash this child's pre-existing mergeinfo. */
6453           mergeinfo_child->pre_merge_mergeinfo = mergeinfo;
6454
6455           /* Note if this child has non-inheritable mergeinfo */
6456           mergeinfo_child->has_noninheritable
6457             = svn_mergeinfo__is_noninheritable(
6458                 mergeinfo_child->pre_merge_mergeinfo, iterpool);
6459
6460           /* Append it.  We'll sort below. */
6461           APR_ARRAY_PUSH(children_with_mergeinfo, svn_client__merge_path_t *)
6462             = svn_client__merge_path_dup(mergeinfo_child, result_pool);
6463         }
6464
6465       /* Sort CHILDREN_WITH_MERGEINFO by each child's path (i.e. as per
6466          compare_merge_path_t_as_paths).  Any subsequent insertions of new
6467          children with insert_child_to_merge() require this ordering. */
6468       qsort(children_with_mergeinfo->elts,
6469             children_with_mergeinfo->nelts,
6470             children_with_mergeinfo->elt_size,
6471             compare_merge_path_t_as_paths);
6472     }
6473
6474   /* Case 2: Switched subtrees
6475      Case 10: Paths at depths of 'empty' or 'files'
6476      Case 11: Paths missing from disk */
6477   pre_merge_status_baton.wc_ctx = ctx->wc_ctx;
6478   switched_subtrees = apr_hash_make(scratch_pool);
6479   pre_merge_status_baton.switched_subtrees = switched_subtrees;
6480   shallow_subtrees = apr_hash_make(scratch_pool);
6481   pre_merge_status_baton.shallow_subtrees = shallow_subtrees;
6482   missing_subtrees = apr_hash_make(scratch_pool);
6483   pre_merge_status_baton.missing_subtrees = missing_subtrees;
6484   pre_merge_status_baton.pool = scratch_pool;
6485   SVN_ERR(svn_wc_walk_status(ctx->wc_ctx,
6486                              target->abspath,
6487                              depth,
6488                              TRUE /* get_all */,
6489                              FALSE /* no_ignore */,
6490                              TRUE /* ignore_text_mods */,
6491                              NULL /* ingore_patterns */,
6492                              pre_merge_status_cb, &pre_merge_status_baton,
6493                              ctx->cancel_func, ctx->cancel_baton,
6494                              scratch_pool));
6495
6496   /* Issue #2915: Raise an error describing the roots of any missing
6497      subtrees, i.e. those that the WC thinks are on disk but have been
6498      removed outside of Subversion. */
6499   if (apr_hash_count(missing_subtrees))
6500     {
6501       apr_hash_index_t *hi;
6502       svn_stringbuf_t *missing_subtree_err_buf =
6503         svn_stringbuf_create(_("Merge tracking not allowed with missing "
6504                                "subtrees; try restoring these items "
6505                                "first:\n"), scratch_pool);
6506
6507       for (hi = apr_hash_first(scratch_pool, missing_subtrees);
6508            hi;
6509            hi = apr_hash_next(hi))
6510         {
6511           svn_pool_clear(iterpool);
6512           svn_stringbuf_appendcstr(missing_subtree_err_buf,
6513                                    svn_dirent_local_style(
6514                                      apr_hash_this_key(hi), iterpool));
6515           svn_stringbuf_appendcstr(missing_subtree_err_buf, "\n");
6516         }
6517
6518       return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE,
6519                               NULL, missing_subtree_err_buf->data);
6520     }
6521
6522   if (apr_hash_count(switched_subtrees))
6523     {
6524       apr_hash_index_t *hi;
6525
6526       for (hi = apr_hash_first(scratch_pool, switched_subtrees);
6527            hi;
6528            hi = apr_hash_next(hi))
6529         {
6530            const char *wc_path = apr_hash_this_key(hi);
6531            svn_client__merge_path_t *child = get_child_with_mergeinfo(
6532              children_with_mergeinfo, wc_path);
6533
6534            if (child)
6535              {
6536                child->switched = TRUE;
6537              }
6538            else
6539              {
6540                svn_client__merge_path_t *switched_child =
6541                  svn_client__merge_path_create(wc_path, result_pool);
6542                switched_child->switched = TRUE;
6543                insert_child_to_merge(children_with_mergeinfo, switched_child,
6544                                      result_pool);
6545              }
6546         }
6547     }
6548
6549   if (apr_hash_count(shallow_subtrees))
6550     {
6551       apr_hash_index_t *hi;
6552
6553       for (hi = apr_hash_first(scratch_pool, shallow_subtrees);
6554            hi;
6555            hi = apr_hash_next(hi))
6556         {
6557            svn_boolean_t new_shallow_child = FALSE;
6558            const char *wc_path = apr_hash_this_key(hi);
6559            svn_depth_t *child_depth = apr_hash_this_val(hi);
6560            svn_client__merge_path_t *shallow_child = get_child_with_mergeinfo(
6561              children_with_mergeinfo, wc_path);
6562
6563            if (shallow_child)
6564              {
6565                if (*child_depth == svn_depth_empty
6566                    || *child_depth == svn_depth_files)
6567                  shallow_child->missing_child = TRUE;
6568              }
6569            else
6570              {
6571                shallow_child = svn_client__merge_path_create(wc_path,
6572                                                              result_pool);
6573                new_shallow_child = TRUE;
6574
6575                if (*child_depth == svn_depth_empty
6576                    || *child_depth == svn_depth_files)
6577                  shallow_child->missing_child = TRUE;
6578              }
6579
6580           /* A little trickery: If PATH doesn't have any mergeinfo or has
6581              only inheritable mergeinfo, we still describe it as having
6582              non-inheritable mergeinfo if it is missing a child due to
6583              a shallow depth.  Why? Because the mergeinfo we'll add to PATH
6584              to describe the merge must be non-inheritable, so PATH's missing
6585              children don't inherit it.  Marking these PATHs as non-
6586              inheritable allows the logic for case 3 to properly account
6587              for PATH's children. */
6588           if (!shallow_child->has_noninheritable
6589               && (*child_depth == svn_depth_empty
6590                   || *child_depth == svn_depth_files))
6591             {
6592               shallow_child->has_noninheritable = TRUE;
6593             }
6594
6595           if (new_shallow_child)
6596             insert_child_to_merge(children_with_mergeinfo, shallow_child,
6597                                   result_pool);
6598        }
6599     }
6600
6601   /* Case 6: Paths absent from disk due to server or user exclusion. */
6602   SVN_ERR(svn_wc__get_excluded_subtrees(&excluded_subtrees,
6603                                         ctx->wc_ctx, target->abspath,
6604                                         result_pool, scratch_pool));
6605   if (excluded_subtrees)
6606     {
6607       apr_hash_index_t *hi;
6608
6609       for (hi = apr_hash_first(scratch_pool, excluded_subtrees);
6610            hi;
6611            hi = apr_hash_next(hi))
6612         {
6613            const char *wc_path = apr_hash_this_key(hi);
6614            svn_client__merge_path_t *child = get_child_with_mergeinfo(
6615              children_with_mergeinfo, wc_path);
6616
6617            if (child)
6618              {
6619                child->absent = TRUE;
6620              }
6621            else
6622              {
6623                svn_client__merge_path_t *absent_child =
6624                  svn_client__merge_path_create(wc_path, result_pool);
6625                absent_child->absent = TRUE;
6626                insert_child_to_merge(children_with_mergeinfo, absent_child,
6627                                      result_pool);
6628              }
6629         }
6630     }
6631
6632   /* Case 7: The merge target MERGE_CMD_BATON->target->abspath is always
6633      present. */
6634   if (!get_child_with_mergeinfo(children_with_mergeinfo,
6635                                 target->abspath))
6636     {
6637       svn_client__merge_path_t *target_child =
6638         svn_client__merge_path_create(target->abspath,
6639                                       result_pool);
6640       insert_child_to_merge(children_with_mergeinfo, target_child,
6641                             result_pool);
6642     }
6643
6644   /* Case 8: Path is an immediate *directory* child of
6645      MERGE_CMD_BATON->target->abspath and DEPTH is svn_depth_immediates.
6646
6647      Case 9: Path is an immediate *file* child of
6648      MERGE_CMD_BATON->target->abspath and DEPTH is svn_depth_files. */
6649   if (depth == svn_depth_immediates || depth == svn_depth_files)
6650     {
6651       int j;
6652       const apr_array_header_t *immediate_children;
6653
6654       SVN_ERR(svn_wc__node_get_children_of_working_node(
6655         &immediate_children, ctx->wc_ctx,
6656         target->abspath, scratch_pool, scratch_pool));
6657
6658       for (j = 0; j < immediate_children->nelts; j++)
6659         {
6660           const char *immediate_child_abspath =
6661             APR_ARRAY_IDX(immediate_children, j, const char *);
6662           svn_node_kind_t immediate_child_kind;
6663
6664           svn_pool_clear(iterpool);
6665           SVN_ERR(svn_wc_read_kind2(&immediate_child_kind,
6666                                     ctx->wc_ctx, immediate_child_abspath,
6667                                     FALSE, FALSE, iterpool));
6668           if ((immediate_child_kind == svn_node_dir
6669                && depth == svn_depth_immediates)
6670               || (immediate_child_kind == svn_node_file
6671                   && depth == svn_depth_files))
6672             {
6673               if (!get_child_with_mergeinfo(children_with_mergeinfo,
6674                                             immediate_child_abspath))
6675                 {
6676                   svn_client__merge_path_t *immediate_child =
6677                     svn_client__merge_path_create(immediate_child_abspath,
6678                                                   result_pool);
6679
6680                   if (immediate_child_kind == svn_node_dir
6681                       && depth == svn_depth_immediates)
6682                     immediate_child->immediate_child_dir = TRUE;
6683
6684                   insert_child_to_merge(children_with_mergeinfo,
6685                                         immediate_child, result_pool);
6686                 }
6687             }
6688         }
6689     }
6690
6691   /* If DEPTH isn't empty then cover cases 3), 4), and 5), possibly adding
6692      elements to CHILDREN_WITH_MERGEINFO. */
6693   if (depth <= svn_depth_empty)
6694     return SVN_NO_ERROR;
6695
6696   for (i = 0; i < children_with_mergeinfo->nelts; i++)
6697     {
6698       svn_client__merge_path_t *child =
6699         APR_ARRAY_IDX(children_with_mergeinfo, i,
6700                       svn_client__merge_path_t *);
6701       svn_pool_clear(iterpool);
6702
6703       /* Case 3) Where merging to a path with a switched child the path
6704          gets non-inheritable mergeinfo for the merge range performed and
6705          the child gets its own set of mergeinfo.  If the switched child
6706          later "returns", e.g. a switched path is unswitched, the child
6707          may not have any explicit mergeinfo.  If the initial merge is
6708          repeated we don't want to repeat the merge for the path, but we
6709          do want to repeat it for the previously switched child.  To
6710          ensure this we check if all of CHILD's non-missing children have
6711          explicit mergeinfo (they should already be present in
6712          CHILDREN_WITH_MERGEINFO if they do).  If not,
6713          add the children without mergeinfo to CHILDREN_WITH_MERGEINFO so
6714          do_directory_merge() will merge them independently.
6715
6716          But that's not enough!  Since do_directory_merge() performs
6717          the merges on the paths in CHILDREN_WITH_MERGEINFO in a depth
6718          first manner it will merge the previously switched path's parent
6719          first.  As part of this merge it will update the parent's
6720          previously non-inheritable mergeinfo and make it inheritable
6721          (since it notices the path has no missing children), then when
6722          do_directory_merge() finally merges the previously missing
6723          child it needs to get mergeinfo from the child's nearest
6724          ancestor, but since do_directory_merge() already tweaked that
6725          mergeinfo, removing the non-inheritable flag, it appears that the
6726          child already has been merged to.  To prevent this we set
6727          override mergeinfo on the child now, before any merging is done,
6728          so it has explicit mergeinfo that reflects only CHILD's
6729          inheritable mergeinfo. */
6730
6731       /* If depth is immediates or files then don't add new children if
6732          CHILD is a subtree of the merge target; those children are below
6733          the operational depth of the merge. */
6734       if (child->has_noninheritable
6735           && (i == 0 || depth == svn_depth_infinity))
6736         {
6737           const apr_array_header_t *children;
6738           int j;
6739
6740           SVN_ERR(svn_wc__node_get_children_of_working_node(
6741                                             &children,
6742                                             ctx->wc_ctx,
6743                                             child->abspath,
6744                                             iterpool, iterpool));
6745           for (j = 0; j < children->nelts; j++)
6746             {
6747               svn_client__merge_path_t *child_of_noninheritable;
6748               const char *child_abspath = APR_ARRAY_IDX(children, j,
6749                                                         const char*);
6750
6751               /* Does this child already exist in CHILDREN_WITH_MERGEINFO?
6752                  If not, create it and insert it into
6753                  CHILDREN_WITH_MERGEINFO and set override mergeinfo on
6754                  it. */
6755               child_of_noninheritable =
6756                 get_child_with_mergeinfo(children_with_mergeinfo,
6757                                          child_abspath);
6758               if (!child_of_noninheritable)
6759                 {
6760                   /* Don't add directory children if DEPTH
6761                      is svn_depth_files. */
6762                   if (depth == svn_depth_files)
6763                     {
6764                       svn_node_kind_t child_kind;
6765                       SVN_ERR(svn_wc_read_kind2(&child_kind,
6766                                                 ctx->wc_ctx, child_abspath,
6767                                                 FALSE, FALSE, iterpool));
6768                       if (child_kind != svn_node_file)
6769                         continue;
6770                     }
6771                   /* else DEPTH is infinity or immediates so we want both
6772                      directory and file children. */
6773
6774                   child_of_noninheritable =
6775                     svn_client__merge_path_create(child_abspath, result_pool);
6776                   child_of_noninheritable->child_of_noninheritable = TRUE;
6777                   insert_child_to_merge(children_with_mergeinfo,
6778                                         child_of_noninheritable,
6779                                         result_pool);
6780                   if (!dry_run && same_repos)
6781                     {
6782                       svn_mergeinfo_t mergeinfo;
6783
6784                       SVN_ERR(svn_client__get_wc_mergeinfo(
6785                         &mergeinfo, NULL,
6786                         svn_mergeinfo_nearest_ancestor,
6787                         child_of_noninheritable->abspath,
6788                         target->abspath, NULL, FALSE,
6789                         ctx, iterpool, iterpool));
6790
6791                       SVN_ERR(svn_client__record_wc_mergeinfo(
6792                         child_of_noninheritable->abspath, mergeinfo,
6793                         FALSE, ctx, iterpool));
6794                     }
6795                 }
6796             }
6797         }
6798       /* Case 4 and 5 are handled by the following function. */
6799       SVN_ERR(insert_parent_and_sibs_of_sw_absent_del_subtree(
6800         children_with_mergeinfo, target, &i, child,
6801         depth, ctx, result_pool));
6802     } /* i < children_with_mergeinfo->nelts */
6803   svn_pool_destroy(iterpool);
6804
6805   return SVN_NO_ERROR;
6806 }
6807
6808
6809 /* Implements the svn_log_entry_receiver_t interface.
6810  *
6811  * BATON is an 'apr_array_header_t *' array of 'svn_revnum_t'.
6812  * Push a copy of LOG_ENTRY->revision onto BATON.  Thus, a
6813  * series of invocations of this callback accumulates the
6814  * corresponding set of revisions into BATON.
6815  */
6816 static svn_error_t *
6817 log_changed_revs(void *baton,
6818                  svn_log_entry_t *log_entry,
6819                  apr_pool_t *pool)
6820 {
6821   apr_array_header_t *revs = baton;
6822
6823   APR_ARRAY_PUSH(revs, svn_revnum_t) = log_entry->revision;
6824   return SVN_NO_ERROR;
6825 }
6826
6827
6828 /* Set *MIN_REV_P to the oldest and *MAX_REV_P to the youngest start or end
6829  * revision occurring in RANGELIST, or to SVN_INVALID_REVNUM if RANGELIST
6830  * is empty. */
6831 static void
6832 merge_range_find_extremes(svn_revnum_t *min_rev_p,
6833                           svn_revnum_t *max_rev_p,
6834                           const svn_rangelist_t *rangelist)
6835 {
6836   int i;
6837
6838   *min_rev_p = SVN_INVALID_REVNUM;
6839   *max_rev_p = SVN_INVALID_REVNUM;
6840   for (i = 0; i < rangelist->nelts; i++)
6841     {
6842       svn_merge_range_t *range
6843         = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
6844       svn_revnum_t range_min = MIN(range->start, range->end);
6845       svn_revnum_t range_max = MAX(range->start, range->end);
6846
6847       if ((! SVN_IS_VALID_REVNUM(*min_rev_p)) || (range_min < *min_rev_p))
6848         *min_rev_p = range_min;
6849       if ((! SVN_IS_VALID_REVNUM(*max_rev_p)) || (range_max > *max_rev_p))
6850         *max_rev_p = range_max;
6851     }
6852 }
6853
6854 /* Wrapper around svn_ra_get_log2(). Invoke RECEIVER with RECEIVER_BATON
6855  * on each commit from YOUNGEST_REV to OLDEST_REV in which TARGET_RELPATH
6856  * changed.  TARGET_RELPATH is relative to RA_SESSION's URL.
6857  * Important: Revision properties are not retrieved by this function for
6858  * performance reasons.
6859  */
6860 static svn_error_t *
6861 get_log(svn_ra_session_t *ra_session,
6862         const char *target_relpath,
6863         svn_revnum_t youngest_rev,
6864         svn_revnum_t oldest_rev,
6865         svn_boolean_t discover_changed_paths,
6866         svn_log_entry_receiver_t receiver,
6867         void *receiver_baton,
6868         apr_pool_t *pool)
6869 {
6870   apr_array_header_t *log_targets;
6871   apr_array_header_t *revprops;
6872
6873   log_targets = apr_array_make(pool, 1, sizeof(const char *));
6874   APR_ARRAY_PUSH(log_targets, const char *) = target_relpath;
6875
6876   revprops = apr_array_make(pool, 0, sizeof(const char *));
6877
6878   SVN_ERR(svn_ra_get_log2(ra_session, log_targets, youngest_rev,
6879                           oldest_rev, 0 /* limit */, discover_changed_paths,
6880                           FALSE /* strict_node_history */,
6881                           FALSE /* include_merged_revisions */,
6882                           revprops, receiver, receiver_baton, pool));
6883
6884   return SVN_NO_ERROR;
6885 }
6886
6887 /* Set *OPERATIVE_RANGES_P to an array of svn_merge_range_t * merge
6888    range objects copied wholesale from RANGES which have the property
6889    that in some revision within that range the object identified by
6890    RA_SESSION was modified (if by "modified" we mean "'svn log' would
6891    return that revision).  *OPERATIVE_RANGES_P is allocated from the
6892    same pool as RANGES, and the ranges within it are shared with
6893    RANGES, too.
6894
6895    *OPERATIVE_RANGES_P may be the same as RANGES (that is, the output
6896    parameter is set only after the input is no longer used).
6897
6898    Use POOL for temporary allocations.  */
6899 static svn_error_t *
6900 remove_noop_merge_ranges(svn_rangelist_t **operative_ranges_p,
6901                          svn_ra_session_t *ra_session,
6902                          const svn_rangelist_t *ranges,
6903                          apr_pool_t *pool)
6904 {
6905   int i;
6906   svn_revnum_t oldest_rev, youngest_rev;
6907   apr_array_header_t *changed_revs =
6908     apr_array_make(pool, ranges->nelts, sizeof(svn_revnum_t));
6909   svn_rangelist_t *operative_ranges =
6910     apr_array_make(ranges->pool, ranges->nelts, ranges->elt_size);
6911
6912   /* Find the revision extremes of the RANGES we have. */
6913   merge_range_find_extremes(&oldest_rev, &youngest_rev, ranges);
6914   if (SVN_IS_VALID_REVNUM(oldest_rev))
6915     oldest_rev++;  /* make it inclusive */
6916
6917   /* Get logs across those ranges, recording which revisions hold
6918      changes to our object's history. */
6919   SVN_ERR(get_log(ra_session, "", youngest_rev, oldest_rev, FALSE,
6920                   log_changed_revs, changed_revs, pool));
6921
6922   /* Are there *any* changes? */
6923   if (changed_revs->nelts)
6924     {
6925       /* Our list of changed revisions should be in youngest-to-oldest
6926          order. */
6927       svn_revnum_t youngest_changed_rev
6928         = APR_ARRAY_IDX(changed_revs, 0, svn_revnum_t);
6929       svn_revnum_t oldest_changed_rev
6930         = APR_ARRAY_IDX(changed_revs, changed_revs->nelts - 1, svn_revnum_t);
6931
6932       /* Now, copy from RANGES to *OPERATIVE_RANGES, filtering out ranges
6933          that aren't operative (by virtue of not having any revisions
6934          represented in the CHANGED_REVS array). */
6935       for (i = 0; i < ranges->nelts; i++)
6936         {
6937           svn_merge_range_t *range = APR_ARRAY_IDX(ranges, i,
6938                                                    svn_merge_range_t *);
6939           svn_revnum_t range_min = MIN(range->start, range->end) + 1;
6940           svn_revnum_t range_max = MAX(range->start, range->end);
6941           int j;
6942
6943           /* If the merge range is entirely outside the range of changed
6944              revisions, we've no use for it. */
6945           if ((range_min > youngest_changed_rev)
6946               || (range_max < oldest_changed_rev))
6947             continue;
6948
6949           /* Walk through the changed_revs to see if any of them fall
6950              inside our current range. */
6951           for (j = 0; j < changed_revs->nelts; j++)
6952             {
6953               svn_revnum_t changed_rev
6954                 = APR_ARRAY_IDX(changed_revs, j, svn_revnum_t);
6955               if ((changed_rev >= range_min) && (changed_rev <= range_max))
6956                 {
6957                   APR_ARRAY_PUSH(operative_ranges, svn_merge_range_t *) =
6958                     range;
6959                   break;
6960                 }
6961             }
6962         }
6963     }
6964
6965   *operative_ranges_p = operative_ranges;
6966   return SVN_NO_ERROR;
6967 }
6968
6969
6970 /*-----------------------------------------------------------------------*/
6971 \f
6972 /*** Merge Source Normalization ***/
6973
6974 /* qsort-compatible sort routine, rating merge_source_t * objects to
6975    be in descending (youngest-to-oldest) order based on their ->loc1->rev
6976    component. */
6977 static int
6978 compare_merge_source_ts(const void *a,
6979                         const void *b)
6980 {
6981   svn_revnum_t a_rev = (*(const merge_source_t *const *)a)->loc1->rev;
6982   svn_revnum_t b_rev = (*(const merge_source_t *const *)b)->loc1->rev;
6983   if (a_rev == b_rev)
6984     return 0;
6985   return a_rev < b_rev ? 1 : -1;
6986 }
6987
6988 /* Set *MERGE_SOURCE_TS_P to a list of merge sources generated by
6989    slicing history location SEGMENTS with a given requested merge
6990    RANGE.  Use SOURCE_LOC for full source URL calculation.
6991
6992    Order the merge sources in *MERGE_SOURCE_TS_P from oldest to
6993    youngest. */
6994 static svn_error_t *
6995 combine_range_with_segments(apr_array_header_t **merge_source_ts_p,
6996                             const svn_merge_range_t *range,
6997                             const apr_array_header_t *segments,
6998                             const svn_client__pathrev_t *source_loc,
6999                             apr_pool_t *pool)
7000 {
7001   apr_array_header_t *merge_source_ts =
7002     apr_array_make(pool, 1, sizeof(merge_source_t *));
7003   svn_revnum_t minrev = MIN(range->start, range->end) + 1;
7004   svn_revnum_t maxrev = MAX(range->start, range->end);
7005   svn_boolean_t subtractive = (range->start > range->end);
7006   int i;
7007
7008   for (i = 0; i < segments->nelts; i++)
7009     {
7010       svn_location_segment_t *segment =
7011         APR_ARRAY_IDX(segments, i, svn_location_segment_t *);
7012       svn_client__pathrev_t *loc1, *loc2;
7013       merge_source_t *merge_source;
7014       const char *path1 = NULL;
7015       svn_revnum_t rev1;
7016
7017       /* If this segment doesn't overlap our range at all, or
7018          represents a gap, ignore it. */
7019       if ((segment->range_end < minrev)
7020           || (segment->range_start > maxrev)
7021           || (! segment->path))
7022         continue;
7023
7024       /* If our range spans a segment boundary, we have to point our
7025          merge_source_t's path1 to the path of the immediately older
7026          segment, else it points to the same location as its path2.  */
7027       rev1 = MAX(segment->range_start, minrev) - 1;
7028       if (minrev <= segment->range_start)
7029         {
7030           if (i > 0)
7031             {
7032               path1 = (APR_ARRAY_IDX(segments, i - 1,
7033                                      svn_location_segment_t *))->path;
7034             }
7035           /* If we've backed PATH1 up into a segment gap, let's back
7036              it up further still to the segment before the gap.  We'll
7037              have to adjust rev1, too. */
7038           if ((! path1) && (i > 1))
7039             {
7040               path1 = (APR_ARRAY_IDX(segments, i - 2,
7041                                      svn_location_segment_t *))->path;
7042               rev1 = (APR_ARRAY_IDX(segments, i - 2,
7043                                     svn_location_segment_t *))->range_end;
7044             }
7045         }
7046       else
7047         {
7048           path1 = apr_pstrdup(pool, segment->path);
7049         }
7050
7051       /* If we don't have two valid paths, we won't know what to do
7052          when merging.  This could happen if someone requested a merge
7053          where the source didn't exist in a particular revision or
7054          something.  The merge code would probably bomb out anyway, so
7055          we'll just *not* create a merge source in this case. */
7056       if (! (path1 && segment->path))
7057         continue;
7058
7059       /* Build our merge source structure. */
7060       loc1 = svn_client__pathrev_create_with_relpath(
7061                source_loc->repos_root_url, source_loc->repos_uuid,
7062                rev1, path1, pool);
7063       loc2 = svn_client__pathrev_create_with_relpath(
7064                source_loc->repos_root_url, source_loc->repos_uuid,
7065                MIN(segment->range_end, maxrev), segment->path, pool);
7066       /* If this is subtractive, reverse the whole calculation. */
7067       if (subtractive)
7068         merge_source = merge_source_create(loc2, loc1, TRUE /* ancestral */,
7069                                            pool);
7070       else
7071         merge_source = merge_source_create(loc1, loc2, TRUE /* ancestral */,
7072                                            pool);
7073
7074       APR_ARRAY_PUSH(merge_source_ts, merge_source_t *) = merge_source;
7075     }
7076
7077   /* If this was a subtractive merge, and we created more than one
7078      merge source, we need to reverse the sort ordering of our sources. */
7079   if (subtractive && (merge_source_ts->nelts > 1))
7080     qsort(merge_source_ts->elts, merge_source_ts->nelts,
7081           merge_source_ts->elt_size, 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          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(conflict_report_t **conflict_report,
10093                                        svn_boolean_t *use_sleep,
10094                                        const merge_target_t *target,
10095                                        svn_ra_session_t *URL1_ra_session,
10096                                        svn_ra_session_t *URL2_ra_session,
10097                                        const merge_source_t *source,
10098                                        const svn_client__pathrev_t *yca,
10099                                        svn_boolean_t same_repos,
10100                                        svn_depth_t depth,
10101                                        svn_boolean_t diff_ignore_ancestry,
10102                                        svn_boolean_t force_delete,
10103                                        svn_boolean_t record_only,
10104                                        svn_boolean_t dry_run,
10105                                        const apr_array_header_t *merge_options,
10106                                        svn_client_ctx_t *ctx,
10107                                        apr_pool_t *result_pool,
10108                                        apr_pool_t *scratch_pool)
10109 {
10110   apr_array_header_t *remove_sources, *add_sources;
10111   apr_hash_t *modified_subtrees = NULL;
10112
10113   /* Sure we could use SCRATCH_POOL throughout this function, but since this
10114      is a wrapper around three separate merges we'll create a subpool we can
10115      clear between each of the three.  If the merge target has a lot of
10116      subtree mergeinfo, then this will help keep memory use in check. */
10117   apr_pool_t *subpool = svn_pool_create(scratch_pool);
10118
10119   assert(session_url_is(URL1_ra_session, source->loc1->url, scratch_pool));
10120   assert(session_url_is(URL2_ra_session, source->loc2->url, scratch_pool));
10121
10122   SVN_ERR_ASSERT(svn_dirent_is_absolute(target->abspath));
10123   SVN_ERR_ASSERT(! source->ancestral);
10124
10125   SVN_ERR(normalize_merge_sources_internal(
10126             &remove_sources, source->loc1,
10127             svn_rangelist__initialize(source->loc1->rev, yca->rev, TRUE,
10128                                       scratch_pool),
10129             URL1_ra_session, ctx, scratch_pool, subpool));
10130
10131   SVN_ERR(normalize_merge_sources_internal(
10132             &add_sources, source->loc2,
10133             svn_rangelist__initialize(yca->rev, source->loc2->rev, TRUE,
10134                                       scratch_pool),
10135             URL2_ra_session, ctx, scratch_pool, subpool));
10136
10137   *conflict_report = NULL;
10138
10139   /* If this isn't a record-only merge, we'll first do a stupid
10140      point-to-point merge... */
10141   if (! record_only)
10142     {
10143       apr_array_header_t *faux_sources =
10144         apr_array_make(scratch_pool, 1, sizeof(merge_source_t *));
10145
10146       modified_subtrees = apr_hash_make(scratch_pool);
10147       APR_ARRAY_PUSH(faux_sources, const merge_source_t *) = source;
10148       SVN_ERR(do_merge(&modified_subtrees, NULL, conflict_report, use_sleep,
10149                        faux_sources, target,
10150                        URL1_ra_session, TRUE, same_repos,
10151                        FALSE /*ignore_mergeinfo*/, diff_ignore_ancestry,
10152                        force_delete, dry_run, FALSE, NULL, TRUE,
10153                        FALSE, depth, merge_options, ctx,
10154                        scratch_pool, subpool));
10155       if (*conflict_report)
10156         {
10157           *conflict_report = conflict_report_dup(*conflict_report, result_pool);
10158           if (! (*conflict_report)->was_last_range)
10159             return SVN_NO_ERROR;
10160         }
10161     }
10162   else if (! same_repos)
10163     {
10164       return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
10165                               _("Merge from foreign repository is not "
10166                                 "compatible with mergeinfo modification"));
10167     }
10168
10169   /* ... and now, if we're doing the mergeinfo thang, we execute a
10170      pair of record-only merges using the real sources we've
10171      calculated.
10172
10173      Issue #3648: We don't actually perform these two record-only merges
10174      on the WC at first, but rather see what each would do and store that
10175      in two mergeinfo catalogs.  We then merge the catalogs together and
10176      then record the result in the WC.  This prevents the second record
10177      only merge from removing legitimate mergeinfo history, from the same
10178      source, that was made in prior merges. */
10179   if (same_repos && !dry_run)
10180     {
10181       svn_mergeinfo_catalog_t add_result_catalog =
10182         apr_hash_make(scratch_pool);
10183       svn_mergeinfo_catalog_t remove_result_catalog =
10184         apr_hash_make(scratch_pool);
10185
10186       notify_mergeinfo_recording(target->abspath, NULL, ctx, scratch_pool);
10187       svn_pool_clear(subpool);
10188       SVN_ERR(do_merge(NULL, add_result_catalog, conflict_report, use_sleep,
10189                        add_sources, target,
10190                        URL1_ra_session, TRUE, same_repos,
10191                        FALSE /*ignore_mergeinfo*/, diff_ignore_ancestry,
10192                        force_delete, dry_run, TRUE,
10193                        modified_subtrees, TRUE,
10194                        TRUE, depth, merge_options, ctx,
10195                        scratch_pool, subpool));
10196       if (*conflict_report)
10197         {
10198           *conflict_report = conflict_report_dup(*conflict_report, result_pool);
10199           if (! (*conflict_report)->was_last_range)
10200             return SVN_NO_ERROR;
10201         }
10202       svn_pool_clear(subpool);
10203       SVN_ERR(do_merge(NULL, remove_result_catalog, conflict_report, use_sleep,
10204                        remove_sources, target,
10205                        URL1_ra_session, TRUE, same_repos,
10206                        FALSE /*ignore_mergeinfo*/, diff_ignore_ancestry,
10207                        force_delete, dry_run, TRUE,
10208                        modified_subtrees, TRUE,
10209                        TRUE, depth, merge_options, ctx,
10210                        scratch_pool, subpool));
10211       if (*conflict_report)
10212         {
10213           *conflict_report = conflict_report_dup(*conflict_report, result_pool);
10214           if (! (*conflict_report)->was_last_range)
10215             return SVN_NO_ERROR;
10216         }
10217       SVN_ERR(svn_mergeinfo_catalog_merge(add_result_catalog,
10218                                           remove_result_catalog,
10219                                           scratch_pool, scratch_pool));
10220       SVN_ERR(svn_client__record_wc_mergeinfo_catalog(add_result_catalog,
10221                                                       ctx, scratch_pool));
10222     }
10223
10224   svn_pool_destroy(subpool);
10225   return SVN_NO_ERROR;
10226 }
10227
10228 /* Perform checks to determine whether the working copy at TARGET_ABSPATH
10229  * can safely be used as a merge target. Checks are performed according to
10230  * the ALLOW_MIXED_REV, ALLOW_LOCAL_MODS, and ALLOW_SWITCHED_SUBTREES
10231  * parameters. If any checks fail, raise SVN_ERR_CLIENT_NOT_READY_TO_MERGE.
10232  *
10233  * E.g. if all the ALLOW_* parameters are FALSE, TARGET_ABSPATH must
10234  * be a single-revision, pristine, unswitched working copy.
10235  * In other words, it must reflect a subtree of the repository as found
10236  * at single revision -- although sparse checkouts are permitted. */
10237 static svn_error_t *
10238 ensure_wc_is_suitable_merge_target(const char *target_abspath,
10239                                    svn_client_ctx_t *ctx,
10240                                    svn_boolean_t allow_mixed_rev,
10241                                    svn_boolean_t allow_local_mods,
10242                                    svn_boolean_t allow_switched_subtrees,
10243                                    apr_pool_t *scratch_pool)
10244 {
10245   svn_node_kind_t target_kind;
10246
10247   /* Check the target exists. */
10248   SVN_ERR(svn_io_check_path(target_abspath, &target_kind, scratch_pool));
10249   if (target_kind == svn_node_none)
10250     return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
10251                              _("Path '%s' does not exist"),
10252                              svn_dirent_local_style(target_abspath,
10253                                                     scratch_pool));
10254   SVN_ERR(svn_wc_read_kind2(&target_kind, ctx->wc_ctx, target_abspath,
10255                             FALSE, FALSE, scratch_pool));
10256   if (target_kind != svn_node_dir && target_kind != svn_node_file)
10257     return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
10258                              _("Merge target '%s' does not exist in the "
10259                                "working copy"), target_abspath);
10260
10261   /* Perform the mixed-revision check first because it's the cheapest one. */
10262   if (! allow_mixed_rev)
10263     {
10264       svn_revnum_t min_rev;
10265       svn_revnum_t max_rev;
10266
10267       SVN_ERR(svn_client_min_max_revisions(&min_rev, &max_rev, target_abspath,
10268                                            FALSE, ctx, scratch_pool));
10269
10270       if (!(SVN_IS_VALID_REVNUM(min_rev) && SVN_IS_VALID_REVNUM(max_rev)))
10271         {
10272           svn_boolean_t is_added;
10273
10274           /* Allow merge into added nodes. */
10275           SVN_ERR(svn_wc__node_is_added(&is_added, ctx->wc_ctx, target_abspath,
10276                                         scratch_pool));
10277           if (is_added)
10278             return SVN_NO_ERROR;
10279           else
10280             return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
10281                                     _("Cannot determine revision of working "
10282                                       "copy"));
10283         }
10284
10285       if (min_rev != max_rev)
10286         return svn_error_createf(SVN_ERR_CLIENT_MERGE_UPDATE_REQUIRED, NULL,
10287                                  _("Cannot merge into mixed-revision working "
10288                                    "copy [%ld:%ld]; try updating first"),
10289                                    min_rev, max_rev);
10290     }
10291
10292   /* Next, check for switched subtrees. */
10293   if (! allow_switched_subtrees)
10294     {
10295       svn_boolean_t is_switched;
10296
10297       SVN_ERR(svn_wc__has_switched_subtrees(&is_switched, ctx->wc_ctx,
10298                                             target_abspath, NULL,
10299                                             scratch_pool));
10300       if (is_switched)
10301         return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
10302                                 _("Cannot merge into a working copy "
10303                                   "with a switched subtree"));
10304     }
10305
10306   /* This is the most expensive check, so it is performed last.*/
10307   if (! allow_local_mods)
10308     {
10309       svn_boolean_t is_modified;
10310
10311       SVN_ERR(svn_wc__has_local_mods(&is_modified, ctx->wc_ctx,
10312                                      target_abspath, TRUE,
10313                                      ctx->cancel_func,
10314                                      ctx->cancel_baton,
10315                                      scratch_pool));
10316       if (is_modified)
10317         return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
10318                                 _("Cannot merge into a working copy "
10319                                   "that has local modifications"));
10320     }
10321
10322   return SVN_NO_ERROR;
10323 }
10324
10325 /* Throw an error if PATH_OR_URL is a path and REVISION isn't a repository
10326  * revision. */
10327 static svn_error_t *
10328 ensure_wc_path_has_repo_revision(const char *path_or_url,
10329                                  const svn_opt_revision_t *revision,
10330                                  apr_pool_t *scratch_pool)
10331 {
10332   if (revision->kind != svn_opt_revision_number
10333       && revision->kind != svn_opt_revision_date
10334       && revision->kind != svn_opt_revision_head
10335       && ! svn_path_is_url(path_or_url))
10336     return svn_error_createf(
10337       SVN_ERR_CLIENT_BAD_REVISION, NULL,
10338       _("Invalid merge source '%s'; a working copy path can only be "
10339         "used with a repository revision (a number, a date, or head)"),
10340       svn_dirent_local_style(path_or_url, scratch_pool));
10341   return SVN_NO_ERROR;
10342 }
10343
10344 /* "Open" the target WC for a merge.  That means:
10345  *   - find out its exact repository location
10346  *   - check the WC for suitability (throw an error if unsuitable)
10347  *
10348  * Set *TARGET_P to a new, fully initialized, target description structure.
10349  *
10350  * ALLOW_MIXED_REV, ALLOW_LOCAL_MODS, ALLOW_SWITCHED_SUBTREES determine
10351  * whether the WC is deemed suitable; see ensure_wc_is_suitable_merge_target()
10352  * for details.
10353  *
10354  * If the node is locally added, the rev and URL will be null/invalid. Some
10355  * kinds of merge can use such a target; others can't.
10356  */
10357 static svn_error_t *
10358 open_target_wc(merge_target_t **target_p,
10359                const char *wc_abspath,
10360                svn_boolean_t allow_mixed_rev,
10361                svn_boolean_t allow_local_mods,
10362                svn_boolean_t allow_switched_subtrees,
10363                svn_client_ctx_t *ctx,
10364                apr_pool_t *result_pool,
10365                apr_pool_t *scratch_pool)
10366 {
10367   merge_target_t *target = apr_palloc(result_pool, sizeof(*target));
10368   svn_client__pathrev_t *origin;
10369
10370   target->abspath = apr_pstrdup(result_pool, wc_abspath);
10371
10372   SVN_ERR(svn_client__wc_node_get_origin(&origin, wc_abspath, ctx,
10373                                          result_pool, scratch_pool));
10374   if (origin)
10375     {
10376       target->loc = *origin;
10377     }
10378   else
10379     {
10380       svn_error_t *err;
10381       /* The node has no location in the repository. It's unversioned or
10382        * locally added or locally deleted.
10383        *
10384        * If it's locally added or deleted, find the repository root
10385        * URL and UUID anyway, and leave the node URL and revision as NULL
10386        * and INVALID.  If it's unversioned, this will throw an error. */
10387       err = svn_wc__node_get_repos_info(NULL, NULL,
10388                                         &target->loc.repos_root_url,
10389                                         &target->loc.repos_uuid,
10390                                         ctx->wc_ctx, wc_abspath,
10391                                         result_pool, scratch_pool);
10392
10393       if (err)
10394         {
10395           if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND
10396               && err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY
10397               && err->apr_err != SVN_ERR_WC_UPGRADE_REQUIRED)
10398             return svn_error_trace(err);
10399
10400           return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, err,
10401                                    _("Merge target '%s' does not exist in the "
10402                                      "working copy"),
10403                                    svn_dirent_local_style(wc_abspath,
10404                                                           scratch_pool));
10405         }
10406
10407       target->loc.rev = SVN_INVALID_REVNUM;
10408       target->loc.url = NULL;
10409     }
10410
10411   SVN_ERR(ensure_wc_is_suitable_merge_target(
10412             wc_abspath, ctx,
10413             allow_mixed_rev, allow_local_mods, allow_switched_subtrees,
10414             scratch_pool));
10415
10416   *target_p = target;
10417   return SVN_NO_ERROR;
10418 }
10419
10420 /*-----------------------------------------------------------------------*/
10421 \f
10422 /*** Public APIs ***/
10423
10424 /* The body of svn_client_merge5(), which see for details.
10425  *
10426  * If SOURCE1 @ REVISION1 is related to SOURCE2 @ REVISION2 then use merge
10427  * tracking (subject to other constraints -- see HONOR_MERGEINFO());
10428  * otherwise disable merge tracking.
10429  *
10430  * IGNORE_MERGEINFO and DIFF_IGNORE_ANCESTRY are as in do_merge().
10431  */
10432 static svn_error_t *
10433 merge_locked(conflict_report_t **conflict_report,
10434              const char *source1,
10435              const svn_opt_revision_t *revision1,
10436              const char *source2,
10437              const svn_opt_revision_t *revision2,
10438              const char *target_abspath,
10439              svn_depth_t depth,
10440              svn_boolean_t ignore_mergeinfo,
10441              svn_boolean_t diff_ignore_ancestry,
10442              svn_boolean_t force_delete,
10443              svn_boolean_t record_only,
10444              svn_boolean_t dry_run,
10445              svn_boolean_t allow_mixed_rev,
10446              const apr_array_header_t *merge_options,
10447              svn_client_ctx_t *ctx,
10448              apr_pool_t *result_pool,
10449              apr_pool_t *scratch_pool)
10450 {
10451   merge_target_t *target;
10452   svn_client__pathrev_t *source1_loc, *source2_loc;
10453   svn_boolean_t sources_related = FALSE;
10454   svn_ra_session_t *ra_session1, *ra_session2;
10455   apr_array_header_t *merge_sources;
10456   svn_error_t *err;
10457   svn_boolean_t use_sleep = FALSE;
10458   svn_client__pathrev_t *yca = NULL;
10459   apr_pool_t *sesspool;
10460   svn_boolean_t same_repos;
10461
10462   /* ### FIXME: This function really ought to do a history check on
10463      the left and right sides of the merge source, and -- if one is an
10464      ancestor of the other -- just call svn_client_merge_peg3() with
10465      the appropriate args. */
10466
10467   SVN_ERR(open_target_wc(&target, target_abspath,
10468                          allow_mixed_rev, TRUE, TRUE,
10469                          ctx, scratch_pool, scratch_pool));
10470
10471   /* Open RA sessions to both sides of our merge source, and resolve URLs
10472    * and revisions. */
10473   sesspool = svn_pool_create(scratch_pool);
10474   SVN_ERR(svn_client__ra_session_from_path2(
10475             &ra_session1, &source1_loc,
10476             source1, NULL, revision1, revision1, ctx, sesspool));
10477   SVN_ERR(svn_client__ra_session_from_path2(
10478             &ra_session2, &source2_loc,
10479             source2, NULL, revision2, revision2, ctx, sesspool));
10480
10481   /* We can't do a diff between different repositories. */
10482   /* ### We should also insist that the root URLs of the two sources match,
10483    *     as we are only carrying around a single source-repos-root from now
10484    *     on, and URL calculations will go wrong if they differ.
10485    *     Alternatively, teach the code to cope with differing root URLs. */
10486   SVN_ERR(check_same_repos(source1_loc, source1_loc->url,
10487                            source2_loc, source2_loc->url,
10488                            FALSE /* strict_urls */, scratch_pool));
10489
10490   /* Do our working copy and sources come from the same repository? */
10491   same_repos = is_same_repos(&target->loc, source1_loc, TRUE /* strict_urls */);
10492
10493   /* Unless we're ignoring ancestry, see if the two sources are related.  */
10494   if (! ignore_mergeinfo)
10495     SVN_ERR(svn_client__get_youngest_common_ancestor(
10496                     &yca, source1_loc, source2_loc, ra_session1, ctx,
10497                     scratch_pool, scratch_pool));
10498
10499   /* Check for a youngest common ancestor.  If we have one, we'll be
10500      doing merge tracking.
10501
10502      So, given a requested merge of the differences between A and
10503      B, and a common ancestor of C, we will find ourselves in one of
10504      four positions, and four different approaches:
10505
10506         A == B == C   there's nothing to merge
10507
10508         A == C != B   we merge the changes between A (or C) and B
10509
10510         B == C != A   we merge the changes between B (or C) and A
10511
10512         A != B != C   we merge the changes between A and B without
10513                       merge recording, then record-only two merges:
10514                       from A to C, and from C to B
10515   */
10516   if (yca)
10517     {
10518       /* Note that our merge sources are related. */
10519       sources_related = TRUE;
10520
10521       /* If the common ancestor matches the right side of our merge,
10522          then we only need to reverse-merge the left side. */
10523       if ((strcmp(yca->url, source2_loc->url) == 0)
10524           && (yca->rev == source2_loc->rev))
10525         {
10526           SVN_ERR(normalize_merge_sources_internal(
10527                     &merge_sources, source1_loc,
10528                     svn_rangelist__initialize(source1_loc->rev, yca->rev, TRUE,
10529                                               scratch_pool),
10530                     ra_session1, ctx, scratch_pool, scratch_pool));
10531         }
10532       /* If the common ancestor matches the left side of our merge,
10533          then we only need to merge the right side. */
10534       else if ((strcmp(yca->url, source1_loc->url) == 0)
10535                && (yca->rev == source1_loc->rev))
10536         {
10537           SVN_ERR(normalize_merge_sources_internal(
10538                     &merge_sources, source2_loc,
10539                     svn_rangelist__initialize(yca->rev, source2_loc->rev, TRUE,
10540                                               scratch_pool),
10541                     ra_session2, ctx, scratch_pool, scratch_pool));
10542         }
10543       /* And otherwise, we need to do both: reverse merge the left
10544          side, and merge the right. */
10545       else
10546         {
10547           merge_source_t source;
10548
10549           source.loc1 = source1_loc;
10550           source.loc2 = source2_loc;
10551           source.ancestral = FALSE;
10552
10553           err = merge_cousins_and_supplement_mergeinfo(conflict_report,
10554                                                        &use_sleep,
10555                                                        target,
10556                                                        ra_session1,
10557                                                        ra_session2,
10558                                                        &source,
10559                                                        yca,
10560                                                        same_repos,
10561                                                        depth,
10562                                                        diff_ignore_ancestry,
10563                                                        force_delete,
10564                                                        record_only, dry_run,
10565                                                        merge_options,
10566                                                        ctx,
10567                                                        result_pool,
10568                                                        scratch_pool);
10569           /* Close our temporary RA sessions (this could've happened
10570              after the second call to normalize_merge_sources() inside
10571              the merge_cousins_and_supplement_mergeinfo() routine). */
10572           svn_pool_destroy(sesspool);
10573
10574           if (use_sleep)
10575             svn_io_sleep_for_timestamps(target->abspath, scratch_pool);
10576
10577           SVN_ERR(err);
10578           return SVN_NO_ERROR;
10579         }
10580     }
10581   else
10582     {
10583       /* Build a single-item merge_source_t array. */
10584       merge_sources = apr_array_make(scratch_pool, 1, sizeof(merge_source_t *));
10585       APR_ARRAY_PUSH(merge_sources, merge_source_t *)
10586         = merge_source_create(source1_loc, source2_loc, FALSE, scratch_pool);
10587     }
10588
10589   err = do_merge(NULL, NULL, conflict_report, &use_sleep,
10590                  merge_sources, target,
10591                  ra_session1, sources_related, same_repos,
10592                  ignore_mergeinfo, diff_ignore_ancestry, force_delete, dry_run,
10593                  record_only, NULL, FALSE, FALSE, depth, merge_options,
10594                  ctx, result_pool, scratch_pool);
10595
10596   /* Close our temporary RA sessions. */
10597   svn_pool_destroy(sesspool);
10598
10599   if (use_sleep)
10600     svn_io_sleep_for_timestamps(target->abspath, scratch_pool);
10601
10602   SVN_ERR(err);
10603   return SVN_NO_ERROR;
10604 }
10605
10606 /* Set *TARGET_ABSPATH to the absolute path of, and *LOCK_ABSPATH to
10607  the absolute path to lock for, TARGET_WCPATH. */
10608 static svn_error_t *
10609 get_target_and_lock_abspath(const char **target_abspath,
10610                             const char **lock_abspath,
10611                             const char *target_wcpath,
10612                             svn_client_ctx_t *ctx,
10613                             apr_pool_t *result_pool)
10614 {
10615   svn_node_kind_t kind;
10616   SVN_ERR(svn_dirent_get_absolute(target_abspath, target_wcpath,
10617                                   result_pool));
10618   SVN_ERR(svn_wc_read_kind2(&kind, ctx->wc_ctx, *target_abspath,
10619                             FALSE, FALSE, result_pool));
10620   if (kind == svn_node_dir)
10621     *lock_abspath = *target_abspath;
10622   else
10623     *lock_abspath = svn_dirent_dirname(*target_abspath, result_pool);
10624
10625   return SVN_NO_ERROR;
10626 }
10627
10628 svn_error_t *
10629 svn_client_merge5(const char *source1,
10630                   const svn_opt_revision_t *revision1,
10631                   const char *source2,
10632                   const svn_opt_revision_t *revision2,
10633                   const char *target_wcpath,
10634                   svn_depth_t depth,
10635                   svn_boolean_t ignore_mergeinfo,
10636                   svn_boolean_t diff_ignore_ancestry,
10637                   svn_boolean_t force_delete,
10638                   svn_boolean_t record_only,
10639                   svn_boolean_t dry_run,
10640                   svn_boolean_t allow_mixed_rev,
10641                   const apr_array_header_t *merge_options,
10642                   svn_client_ctx_t *ctx,
10643                   apr_pool_t *pool)
10644 {
10645   const char *target_abspath, *lock_abspath;
10646   conflict_report_t *conflict_report;
10647
10648   /* Sanity check our input -- we require specified revisions,
10649    * and either 2 paths or 2 URLs. */
10650   if ((revision1->kind == svn_opt_revision_unspecified)
10651       || (revision2->kind == svn_opt_revision_unspecified))
10652     return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL,
10653                             _("Not all required revisions are specified"));
10654   if (svn_path_is_url(source1) != svn_path_is_url(source2))
10655     return svn_error_create(SVN_ERR_ILLEGAL_TARGET, NULL,
10656                             _("Merge sources must both be "
10657                               "either paths or URLs"));
10658   /* A WC path must be used with a repository revision, as we can't
10659    * (currently) use the WC itself as a source, we can only read the URL
10660    * from it and use that. */
10661   SVN_ERR(ensure_wc_path_has_repo_revision(source1, revision1, pool));
10662   SVN_ERR(ensure_wc_path_has_repo_revision(source2, revision2, pool));
10663
10664   SVN_ERR(get_target_and_lock_abspath(&target_abspath, &lock_abspath,
10665                                       target_wcpath, ctx, pool));
10666
10667   if (!dry_run)
10668     SVN_WC__CALL_WITH_WRITE_LOCK(
10669       merge_locked(&conflict_report,
10670                    source1, revision1, source2, revision2,
10671                    target_abspath, depth, ignore_mergeinfo,
10672                    diff_ignore_ancestry,
10673                    force_delete, record_only, dry_run,
10674                    allow_mixed_rev, merge_options, ctx, pool, pool),
10675       ctx->wc_ctx, lock_abspath, FALSE /* lock_anchor */, pool);
10676   else
10677     SVN_ERR(merge_locked(&conflict_report,
10678                    source1, revision1, source2, revision2,
10679                    target_abspath, depth, ignore_mergeinfo,
10680                    diff_ignore_ancestry,
10681                    force_delete, record_only, dry_run,
10682                    allow_mixed_rev, merge_options, ctx, pool, pool));
10683
10684   SVN_ERR(make_merge_conflict_error(conflict_report, pool));
10685   return SVN_NO_ERROR;
10686 }
10687
10688
10689 /* Check if mergeinfo for a given path is described explicitly or via
10690    inheritance in a mergeinfo catalog.
10691
10692    If REPOS_REL_PATH exists in CATALOG and has mergeinfo containing
10693    MERGEINFO, then set *IN_CATALOG to TRUE.  If REPOS_REL_PATH does
10694    not exist in CATALOG, then find its nearest parent which does exist.
10695    If the mergeinfo REPOS_REL_PATH would inherit from that parent
10696    contains MERGEINFO then set *IN_CATALOG to TRUE.  Set *IN_CATALOG
10697    to FALSE in all other cases.
10698
10699    Set *CAT_KEY_PATH to the key path in CATALOG for REPOS_REL_PATH's
10700    explicit or inherited mergeinfo.  If no explicit or inherited mergeinfo
10701    is found for REPOS_REL_PATH then set *CAT_KEY_PATH to NULL.
10702
10703    User RESULT_POOL to allocate *CAT_KEY_PATH.  Use SCRATCH_POOL for
10704    temporary allocations. */
10705 static svn_error_t *
10706 mergeinfo_in_catalog(svn_boolean_t *in_catalog,
10707                      const char **cat_key_path,
10708                      const char *repos_rel_path,
10709                      svn_mergeinfo_t mergeinfo,
10710                      svn_mergeinfo_catalog_t catalog,
10711                      apr_pool_t *result_pool,
10712                      apr_pool_t *scratch_pool)
10713 {
10714   const char *walk_path = NULL;
10715
10716   *in_catalog = FALSE;
10717   *cat_key_path = NULL;
10718
10719   if (mergeinfo && catalog && apr_hash_count(catalog))
10720     {
10721       const char *path = repos_rel_path;
10722
10723       /* Start with the assumption there is no explicit or inherited
10724          mergeinfo for REPOS_REL_PATH in CATALOG. */
10725       svn_mergeinfo_t mergeinfo_in_cat = NULL;
10726
10727       while (1)
10728         {
10729           mergeinfo_in_cat = svn_hash_gets(catalog, path);
10730
10731           if (mergeinfo_in_cat) /* Found it! */
10732             {
10733               *cat_key_path = apr_pstrdup(result_pool, path);
10734               break;
10735             }
10736           else /* Look for inherited mergeinfo. */
10737             {
10738               walk_path = svn_relpath_join(svn_relpath_basename(path,
10739                                                                 scratch_pool),
10740                                            walk_path ? walk_path : "",
10741                                            scratch_pool);
10742               path = svn_relpath_dirname(path, scratch_pool);
10743
10744               if (path[0] == '\0') /* No mergeinfo to inherit. */
10745                 break;
10746             }
10747         }
10748
10749       if (mergeinfo_in_cat)
10750         {
10751           if (walk_path)
10752             SVN_ERR(svn_mergeinfo__add_suffix_to_mergeinfo(&mergeinfo_in_cat,
10753                                                            mergeinfo_in_cat,
10754                                                            walk_path,
10755                                                            scratch_pool,
10756                                                            scratch_pool));
10757           SVN_ERR(svn_mergeinfo_intersect2(&mergeinfo_in_cat,
10758                                            mergeinfo_in_cat, mergeinfo,
10759                                            TRUE,
10760                                            scratch_pool, scratch_pool));
10761           SVN_ERR(svn_mergeinfo__equals(in_catalog, mergeinfo_in_cat,
10762                                         mergeinfo, TRUE, scratch_pool));
10763         }
10764     }
10765
10766   return SVN_NO_ERROR;
10767 }
10768
10769 /* A svn_log_entry_receiver_t baton for log_find_operative_revs(). */
10770 typedef struct log_find_operative_baton_t
10771 {
10772   /* The catalog of explicit mergeinfo on a reintegrate source. */
10773   svn_mergeinfo_catalog_t merged_catalog;
10774
10775   /* The catalog of unmerged history from the reintegrate target to
10776      the source which we will create.  Allocated in RESULT_POOL. */
10777   svn_mergeinfo_catalog_t unmerged_catalog;
10778
10779   /* The repository absolute path of the reintegrate target. */
10780   const char *target_fspath;
10781
10782   /* The path of the reintegrate source relative to the repository root. */
10783   const char *source_repos_rel_path;
10784
10785   apr_pool_t *result_pool;
10786 } log_find_operative_baton_t;
10787
10788 /* A svn_log_entry_receiver_t callback for find_unsynced_ranges(). */
10789 static svn_error_t *
10790 log_find_operative_revs(void *baton,
10791                         svn_log_entry_t *log_entry,
10792                         apr_pool_t *pool)
10793 {
10794   log_find_operative_baton_t *log_baton = baton;
10795   apr_hash_index_t *hi;
10796   svn_revnum_t revision;
10797
10798   /* It's possible that authz restrictions on the merge source prevent us
10799      from knowing about any of the changes for LOG_ENTRY->REVISION. */
10800   if (!log_entry->changed_paths2)
10801     return SVN_NO_ERROR;
10802
10803   revision = log_entry->revision;
10804
10805   for (hi = apr_hash_first(pool, log_entry->changed_paths2);
10806        hi;
10807        hi = apr_hash_next(hi))
10808     {
10809       const char *subtree_missing_this_rev;
10810       const char *path = apr_hash_this_key(hi);
10811       const char *rel_path;
10812       const char *source_rel_path;
10813       svn_boolean_t in_catalog;
10814       svn_mergeinfo_t log_entry_as_mergeinfo;
10815
10816       rel_path = svn_fspath__skip_ancestor(log_baton->target_fspath, path);
10817       /* Easy out: The path is not within the tree of interest. */
10818       if (rel_path == NULL)
10819         continue;
10820
10821       source_rel_path = svn_relpath_join(log_baton->source_repos_rel_path,
10822                                          rel_path, pool);
10823
10824       SVN_ERR(svn_mergeinfo_parse(&log_entry_as_mergeinfo,
10825                                   apr_psprintf(pool, "%s:%ld",
10826                                                path, revision),
10827                                   pool));
10828
10829       SVN_ERR(mergeinfo_in_catalog(&in_catalog, &subtree_missing_this_rev,
10830                                    source_rel_path, log_entry_as_mergeinfo,
10831                                    log_baton->merged_catalog,
10832                                    pool, pool));
10833
10834       if (!in_catalog)
10835         {
10836           svn_mergeinfo_t unmerged_for_key;
10837           const char *suffix, *missing_path;
10838
10839           /* If there is no mergeinfo on the source tree we'll say
10840              the "subtree" missing this revision is the root of the
10841              source. */
10842           if (!subtree_missing_this_rev)
10843             subtree_missing_this_rev = log_baton->source_repos_rel_path;
10844
10845           suffix = svn_relpath_skip_ancestor(subtree_missing_this_rev,
10846                                              source_rel_path);
10847           if (suffix && suffix[0] != '\0')
10848             {
10849               missing_path = apr_pstrmemdup(pool, path,
10850                                             strlen(path) - strlen(suffix) - 1);
10851             }
10852           else
10853             {
10854               missing_path = path;
10855             }
10856
10857           SVN_ERR(svn_mergeinfo_parse(&log_entry_as_mergeinfo,
10858                                       apr_psprintf(pool, "%s:%ld",
10859                                                    missing_path, revision),
10860                                       log_baton->result_pool));
10861           unmerged_for_key = svn_hash_gets(log_baton->unmerged_catalog,
10862                                            subtree_missing_this_rev);
10863
10864           if (unmerged_for_key)
10865             {
10866               SVN_ERR(svn_mergeinfo_merge2(unmerged_for_key,
10867                                            log_entry_as_mergeinfo,
10868                                            log_baton->result_pool,
10869                                            pool));
10870             }
10871           else
10872             {
10873               svn_hash_sets(log_baton->unmerged_catalog,
10874                             apr_pstrdup(log_baton->result_pool,
10875                                         subtree_missing_this_rev),
10876                             log_entry_as_mergeinfo);
10877             }
10878
10879         }
10880     }
10881   return SVN_NO_ERROR;
10882 }
10883
10884 /* Determine if the mergeinfo on a reintegrate source SOURCE_LOC,
10885    reflects that the source is fully synced with the reintegrate target
10886    TARGET_LOC, even if a naive interpretation of the source's
10887    mergeinfo says otherwise -- See issue #3577.
10888
10889    UNMERGED_CATALOG represents the history (as mergeinfo) from
10890    TARGET_LOC that is not represented in SOURCE_LOC's
10891    explicit/inherited mergeinfo as represented by MERGED_CATALOG.
10892    MERGED_CATALOG may be empty if the source has no explicit or inherited
10893    mergeinfo.
10894
10895    Check that all of the unmerged revisions in UNMERGED_CATALOG's
10896    mergeinfos are "phantoms", that is, one of the following conditions holds:
10897
10898      1) The revision affects no corresponding paths in SOURCE_LOC.
10899
10900      2) The revision affects corresponding paths in SOURCE_LOC,
10901         but based on the mergeinfo in MERGED_CATALOG, the change was
10902         previously merged.
10903
10904    Make a deep copy, allocated in RESULT_POOL, of any portions of
10905    UNMERGED_CATALOG that are not phantoms, to TRUE_UNMERGED_CATALOG.
10906
10907    Note: The keys in all mergeinfo catalogs used here are relative to the
10908    root of the repository.
10909
10910    RA_SESSION is an RA session open to the repository of TARGET_LOC; it may
10911    be temporarily reparented within this function.
10912
10913    Use SCRATCH_POOL for all temporary allocations. */
10914 static svn_error_t *
10915 find_unsynced_ranges(const svn_client__pathrev_t *source_loc,
10916                      const svn_client__pathrev_t *target_loc,
10917                      svn_mergeinfo_catalog_t unmerged_catalog,
10918                      svn_mergeinfo_catalog_t merged_catalog,
10919                      svn_mergeinfo_catalog_t true_unmerged_catalog,
10920                      svn_ra_session_t *ra_session,
10921                      apr_pool_t *result_pool,
10922                      apr_pool_t *scratch_pool)
10923 {
10924   svn_rangelist_t *potentially_unmerged_ranges = NULL;
10925
10926   /* Convert all the unmerged history to a rangelist. */
10927   if (apr_hash_count(unmerged_catalog))
10928     {
10929       apr_hash_index_t *hi_catalog;
10930
10931       potentially_unmerged_ranges =
10932         apr_array_make(scratch_pool, 1, sizeof(svn_merge_range_t *));
10933
10934       for (hi_catalog = apr_hash_first(scratch_pool, unmerged_catalog);
10935            hi_catalog;
10936            hi_catalog = apr_hash_next(hi_catalog))
10937         {
10938           svn_mergeinfo_t mergeinfo = apr_hash_this_val(hi_catalog);
10939
10940           SVN_ERR(svn_rangelist__merge_many(potentially_unmerged_ranges,
10941                                             mergeinfo,
10942                                             scratch_pool, scratch_pool));
10943         }
10944     }
10945
10946   /* Find any unmerged revisions which both affect the source and
10947      are not yet merged to it. */
10948   if (potentially_unmerged_ranges)
10949     {
10950       svn_revnum_t oldest_rev =
10951         (APR_ARRAY_IDX(potentially_unmerged_ranges,
10952                        0,
10953                        svn_merge_range_t *))->start + 1;
10954       svn_revnum_t youngest_rev =
10955         (APR_ARRAY_IDX(potentially_unmerged_ranges,
10956                        potentially_unmerged_ranges->nelts - 1,
10957                        svn_merge_range_t *))->end;
10958       log_find_operative_baton_t log_baton;
10959       const char *old_session_url;
10960       svn_error_t *err;
10961
10962       log_baton.merged_catalog = merged_catalog;
10963       log_baton.unmerged_catalog = true_unmerged_catalog;
10964       log_baton.source_repos_rel_path
10965         = svn_client__pathrev_relpath(source_loc, scratch_pool);
10966       log_baton.target_fspath
10967         = svn_client__pathrev_fspath(target_loc, scratch_pool);
10968       log_baton.result_pool = result_pool;
10969
10970       SVN_ERR(svn_client__ensure_ra_session_url(
10971                 &old_session_url, ra_session, target_loc->url, scratch_pool));
10972       err = get_log(ra_session, "", youngest_rev, oldest_rev,
10973                     TRUE, /* discover_changed_paths */
10974                     log_find_operative_revs, &log_baton,
10975                     scratch_pool);
10976       SVN_ERR(svn_error_compose_create(
10977                 err, svn_ra_reparent(ra_session, old_session_url, scratch_pool)));
10978     }
10979
10980   return SVN_NO_ERROR;
10981 }
10982
10983
10984 /* Find the youngest revision that has been merged from target to source.
10985  *
10986  * If any location in TARGET_HISTORY_AS_MERGEINFO is mentioned in
10987  * SOURCE_MERGEINFO, then we know that at least one merge was done from the
10988  * target to the source.  In that case, set *YOUNGEST_MERGED_REV to the
10989  * youngest revision of that intersection (unless *YOUNGEST_MERGED_REV is
10990  * already younger than that).  Otherwise, leave *YOUNGEST_MERGED_REV alone.
10991  */
10992 static svn_error_t *
10993 find_youngest_merged_rev(svn_revnum_t *youngest_merged_rev,
10994                          svn_mergeinfo_t target_history_as_mergeinfo,
10995                          svn_mergeinfo_t source_mergeinfo,
10996                          apr_pool_t *scratch_pool)
10997 {
10998   svn_mergeinfo_t explicit_source_target_history_intersection;
10999
11000   SVN_ERR(svn_mergeinfo_intersect2(
11001             &explicit_source_target_history_intersection,
11002             source_mergeinfo, target_history_as_mergeinfo, TRUE,
11003             scratch_pool, scratch_pool));
11004   if (apr_hash_count(explicit_source_target_history_intersection))
11005     {
11006       svn_revnum_t old_rev, young_rev;
11007
11008       /* Keep track of the youngest revision merged from target to source. */
11009       SVN_ERR(svn_mergeinfo__get_range_endpoints(
11010                 &young_rev, &old_rev,
11011                 explicit_source_target_history_intersection, scratch_pool));
11012       if (!SVN_IS_VALID_REVNUM(*youngest_merged_rev)
11013           || (young_rev > *youngest_merged_rev))
11014         *youngest_merged_rev = young_rev;
11015     }
11016
11017   return SVN_NO_ERROR;
11018 }
11019
11020 /* Set *FILTERED_MERGEINFO_P to the parts of TARGET_HISTORY_AS_MERGEINFO
11021  * that are not present in the source branch.
11022  *
11023  * SOURCE_MERGEINFO is the explicit or inherited mergeinfo of the source
11024  * branch SOURCE_PATHREV.  Extend SOURCE_MERGEINFO, modifying it in
11025  * place, to include the natural history (implicit mergeinfo) of
11026  * SOURCE_PATHREV.  ### But make these additions in SCRATCH_POOL.
11027  *
11028  * SOURCE_RA_SESSION is an RA session open to the repository containing
11029  * SOURCE_PATHREV; it may be temporarily reparented within this function.
11030  *
11031  * ### [JAF] This function is named '..._subroutine' simply because I
11032  *     factored it out based on code similarity, without knowing what it's
11033  *     purpose is.  We should clarify its purpose and choose a better name.
11034  */
11035 static svn_error_t *
11036 find_unmerged_mergeinfo_subroutine(svn_mergeinfo_t *filtered_mergeinfo_p,
11037                                    svn_mergeinfo_t target_history_as_mergeinfo,
11038                                    svn_mergeinfo_t source_mergeinfo,
11039                                    const svn_client__pathrev_t *source_pathrev,
11040                                    svn_ra_session_t *source_ra_session,
11041                                    svn_client_ctx_t *ctx,
11042                                    apr_pool_t *result_pool,
11043                                    apr_pool_t *scratch_pool)
11044 {
11045   svn_mergeinfo_t source_history_as_mergeinfo;
11046
11047   /* Get the source path's natural history and merge it into source
11048      path's explicit or inherited mergeinfo. */
11049   SVN_ERR(svn_client__get_history_as_mergeinfo(
11050             &source_history_as_mergeinfo, NULL /* has_rev_zero_history */,
11051             source_pathrev, source_pathrev->rev, SVN_INVALID_REVNUM,
11052             source_ra_session, ctx, scratch_pool));
11053   SVN_ERR(svn_mergeinfo_merge2(source_mergeinfo,
11054                                source_history_as_mergeinfo,
11055                                scratch_pool, scratch_pool));
11056
11057   /* Now source_mergeinfo represents everything we know about
11058      source_path's history.  Now we need to know what part, if any, of the
11059      corresponding target's history is *not* part of source_path's total
11060      history; because it is neither shared history nor was it ever merged
11061      from the target to the source. */
11062   SVN_ERR(svn_mergeinfo_remove2(filtered_mergeinfo_p,
11063                                 source_mergeinfo,
11064                                 target_history_as_mergeinfo, TRUE,
11065                                 result_pool, scratch_pool));
11066   return SVN_NO_ERROR;
11067 }
11068
11069 /* Helper for calculate_left_hand_side() which produces a mergeinfo catalog
11070    describing what parts of of the reintegrate target have not previously been
11071    merged to the reintegrate source.
11072
11073    SOURCE_CATALOG is the collection of explicit mergeinfo on SOURCE_LOC and
11074    all its children, i.e. the mergeinfo catalog for the reintegrate source.
11075
11076    TARGET_HISTORY_HASH is a hash of (const char *) paths mapped to
11077    svn_mergeinfo_t representing the location history.  Each of these
11078    path keys represent a path in the reintegrate target, relative to the
11079    repository root, which has explicit mergeinfo and/or is the reintegrate
11080    target itself.  The svn_mergeinfo_t's contain the natural history of each
11081    path@TARGET_REV.  Effectively this is the mergeinfo catalog on the
11082    reintegrate target.
11083
11084    YC_ANCESTOR_REV is the revision of the youngest common ancestor of the
11085    reintegrate source and the reintegrate target.
11086
11087    SOURCE_LOC is the reintegrate source.
11088
11089    SOURCE_RA_SESSION is a session opened to the URL of SOURCE_LOC
11090    and TARGET_RA_SESSION is open to TARGET->loc.url.
11091
11092    For each entry in TARGET_HISTORY_HASH check that the history it
11093    represents is contained in either the explicit mergeinfo for the
11094    corresponding path in SOURCE_CATALOG, the corresponding path's inherited
11095    mergeinfo (if no explicit mergeinfo for the path is found in
11096    SOURCE_CATALOG), or the corresponding path's natural history.  Populate
11097    *UNMERGED_TO_SOURCE_CATALOG with the corresponding source paths mapped to
11098    the mergeinfo from the target's natural history which is *not* found.  Also
11099    include any mergeinfo from SOURCE_CATALOG which explicitly describes the
11100    target's history but for which *no* entry was found in
11101    TARGET_HISTORY_HASH.
11102
11103    If no part of TARGET_HISTORY_HASH is found in SOURCE_CATALOG set
11104    *YOUNGEST_MERGED_REV to SVN_INVALID_REVNUM; otherwise set it to the youngest
11105    revision previously merged from the target to the source, and filter
11106    *UNMERGED_TO_SOURCE_CATALOG so that it contains no ranges greater than
11107    *YOUNGEST_MERGED_REV.
11108
11109    *UNMERGED_TO_SOURCE_CATALOG is (deeply) allocated in RESULT_POOL.
11110    SCRATCH_POOL is used for all temporary allocations.  */
11111 static svn_error_t *
11112 find_unmerged_mergeinfo(svn_mergeinfo_catalog_t *unmerged_to_source_catalog,
11113                         svn_revnum_t *youngest_merged_rev,
11114                         svn_revnum_t yc_ancestor_rev,
11115                         svn_mergeinfo_catalog_t source_catalog,
11116                         apr_hash_t *target_history_hash,
11117                         const svn_client__pathrev_t *source_loc,
11118                         const merge_target_t *target,
11119                         svn_ra_session_t *source_ra_session,
11120                         svn_ra_session_t *target_ra_session,
11121                         svn_client_ctx_t *ctx,
11122                         apr_pool_t *result_pool,
11123                         apr_pool_t *scratch_pool)
11124 {
11125   const char *source_repos_rel_path
11126     = svn_client__pathrev_relpath(source_loc, scratch_pool);
11127   const char *target_repos_rel_path
11128     = svn_client__pathrev_relpath(&target->loc, scratch_pool);
11129   apr_hash_index_t *hi;
11130   svn_mergeinfo_catalog_t new_catalog = apr_hash_make(result_pool);
11131   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
11132
11133   assert(session_url_is(source_ra_session, source_loc->url, scratch_pool));
11134   assert(session_url_is(target_ra_session, target->loc.url, scratch_pool));
11135
11136   *youngest_merged_rev = SVN_INVALID_REVNUM;
11137
11138   /* Examine the natural history of each path in the reintegrate target
11139      with explicit mergeinfo. */
11140   for (hi = apr_hash_first(scratch_pool, target_history_hash);
11141        hi;
11142        hi = apr_hash_next(hi))
11143     {
11144       const char *target_path = apr_hash_this_key(hi);
11145       svn_mergeinfo_t target_history_as_mergeinfo = apr_hash_this_val(hi);
11146       const char *path_rel_to_session
11147         = svn_relpath_skip_ancestor(target_repos_rel_path, target_path);
11148       const char *source_path;
11149       svn_client__pathrev_t *source_pathrev;
11150       svn_mergeinfo_t source_mergeinfo, filtered_mergeinfo;
11151
11152       svn_pool_clear(iterpool);
11153
11154       source_path = svn_relpath_join(source_repos_rel_path,
11155                                      path_rel_to_session, iterpool);
11156       source_pathrev = svn_client__pathrev_join_relpath(
11157                          source_loc, path_rel_to_session, iterpool);
11158
11159       /* Remove any target history that is also part of the source's history,
11160          i.e. their common ancestry.  By definition this has already been
11161          "merged" from the target to the source.  If the source has explicit
11162          self referential mergeinfo it would intersect with the target's
11163          history below, making it appear that some merges had been done from
11164          the target to the source, when this might not actually be the case. */
11165       SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
11166         &target_history_as_mergeinfo, target_history_as_mergeinfo,
11167         source_loc->rev, yc_ancestor_rev, TRUE, iterpool, iterpool));
11168
11169       /* Look for any explicit mergeinfo on the source path corresponding to
11170          the target path.  If we find any remove that from SOURCE_CATALOG.
11171          When this iteration over TARGET_HISTORY_HASH is complete all that
11172          should be left in SOURCE_CATALOG are subtrees that have explicit
11173          mergeinfo on the reintegrate source where there is no corresponding
11174          explicit mergeinfo on the reintegrate target. */
11175       source_mergeinfo = svn_hash_gets(source_catalog, source_path);
11176       if (source_mergeinfo)
11177         {
11178           svn_hash_sets(source_catalog, source_path, NULL);
11179
11180           SVN_ERR(find_youngest_merged_rev(youngest_merged_rev,
11181                                            target_history_as_mergeinfo,
11182                                            source_mergeinfo,
11183                                            iterpool));
11184         }
11185       else
11186         {
11187           /* There is no mergeinfo on source_path *or* source_path doesn't
11188              exist at all.  If simply doesn't exist we can ignore it
11189              altogether. */
11190           svn_node_kind_t kind;
11191
11192           SVN_ERR(svn_ra_check_path(source_ra_session,
11193                                     path_rel_to_session,
11194                                     source_loc->rev, &kind, iterpool));
11195           if (kind == svn_node_none)
11196               continue;
11197           /* Else source_path does exist though it has no explicit mergeinfo.
11198              Find its inherited mergeinfo.  If it doesn't have any then simply
11199              set source_mergeinfo to an empty hash. */
11200           SVN_ERR(svn_client__get_repos_mergeinfo(
11201                     &source_mergeinfo, source_ra_session,
11202                     source_pathrev->url, source_pathrev->rev,
11203                     svn_mergeinfo_inherited, FALSE /*squelch_incapable*/,
11204                     iterpool));
11205           if (!source_mergeinfo)
11206             source_mergeinfo = apr_hash_make(iterpool);
11207         }
11208
11209       /* Use scratch_pool rather than iterpool because filtered_mergeinfo
11210          is going into new_catalog below and needs to last to the end of
11211          this function. */
11212       SVN_ERR(find_unmerged_mergeinfo_subroutine(
11213                 &filtered_mergeinfo, target_history_as_mergeinfo,
11214                 source_mergeinfo, source_pathrev,
11215                 source_ra_session, ctx, scratch_pool, iterpool));
11216       svn_hash_sets(new_catalog, apr_pstrdup(scratch_pool, source_path),
11217                     filtered_mergeinfo);
11218     }
11219
11220   /* Are there any subtrees with explicit mergeinfo still left in the merge
11221      source where there was no explicit mergeinfo for the corresponding path
11222      in the merge target?  If so, add the intersection of those path's
11223      mergeinfo and the corresponding target path's mergeinfo to
11224      new_catalog. */
11225   for (hi = apr_hash_first(scratch_pool, source_catalog);
11226        hi;
11227        hi = apr_hash_next(hi))
11228     {
11229       const char *source_path = apr_hash_this_key(hi);
11230       const char *path_rel_to_session =
11231         svn_relpath_skip_ancestor(source_repos_rel_path, source_path);
11232       const char *source_url;
11233       svn_mergeinfo_t source_mergeinfo = apr_hash_this_val(hi);
11234       svn_mergeinfo_t filtered_mergeinfo;
11235       svn_client__pathrev_t *target_pathrev;
11236       svn_mergeinfo_t target_history_as_mergeinfo;
11237       svn_error_t *err;
11238
11239       svn_pool_clear(iterpool);
11240
11241       source_url = svn_path_url_add_component2(source_loc->url,
11242                                                path_rel_to_session, iterpool);
11243       target_pathrev = svn_client__pathrev_join_relpath(
11244                          &target->loc, path_rel_to_session, iterpool);
11245       err = svn_client__get_history_as_mergeinfo(&target_history_as_mergeinfo,
11246                                                  NULL /* has_rev_zero_history */,
11247                                                  target_pathrev,
11248                                                  target->loc.rev,
11249                                                  SVN_INVALID_REVNUM,
11250                                                  target_ra_session,
11251                                                  ctx, iterpool);
11252       if (err)
11253         {
11254           if (err->apr_err == SVN_ERR_FS_NOT_FOUND
11255               || err->apr_err == SVN_ERR_RA_DAV_REQUEST_FAILED)
11256             {
11257               /* This path with explicit mergeinfo in the source doesn't
11258                  exist on the target. */
11259               svn_error_clear(err);
11260               err = NULL;
11261             }
11262           else
11263             {
11264               return svn_error_trace(err);
11265             }
11266         }
11267       else
11268         {
11269           svn_client__pathrev_t *pathrev;
11270
11271           SVN_ERR(find_youngest_merged_rev(youngest_merged_rev,
11272                                            target_history_as_mergeinfo,
11273                                            source_mergeinfo,
11274                                            iterpool));
11275
11276           /* Use scratch_pool rather than iterpool because filtered_mergeinfo
11277              is going into new_catalog below and needs to last to the end of
11278              this function. */
11279           /* ### Why looking at SOURCE_url at TARGET_rev? */
11280           SVN_ERR(svn_client__pathrev_create_with_session(
11281                     &pathrev, source_ra_session, target->loc.rev, source_url,
11282                     iterpool));
11283           SVN_ERR(find_unmerged_mergeinfo_subroutine(
11284                     &filtered_mergeinfo, target_history_as_mergeinfo,
11285                     source_mergeinfo, pathrev,
11286                     source_ra_session, ctx, scratch_pool, iterpool));
11287           if (apr_hash_count(filtered_mergeinfo))
11288             svn_hash_sets(new_catalog,
11289                           apr_pstrdup(scratch_pool, source_path),
11290                           filtered_mergeinfo);
11291         }
11292     }
11293
11294   /* Limit new_catalog to the youngest revisions previously merged from
11295      the target to the source. */
11296   if (SVN_IS_VALID_REVNUM(*youngest_merged_rev))
11297     SVN_ERR(svn_mergeinfo__filter_catalog_by_ranges(&new_catalog,
11298                                                     new_catalog,
11299                                                     *youngest_merged_rev,
11300                                                     0, /* No oldest bound. */
11301                                                     TRUE,
11302                                                     scratch_pool,
11303                                                     scratch_pool));
11304
11305   /* Make a shiny new copy before blowing away all the temporary pools. */
11306   *unmerged_to_source_catalog = svn_mergeinfo_catalog_dup(new_catalog,
11307                                                           result_pool);
11308   svn_pool_destroy(iterpool);
11309   return SVN_NO_ERROR;
11310 }
11311
11312 /* Helper for svn_client_merge_reintegrate() which calculates the
11313    'left hand side' of the underlying two-URL merge that a --reintegrate
11314    merge actually performs.  If no merge should be performed, set
11315    *LEFT_P to NULL.
11316
11317    TARGET->abspath is the absolute working copy path of the reintegrate
11318    merge.
11319
11320    SOURCE_LOC is the reintegrate source.
11321
11322    SUBTREES_WITH_MERGEINFO is a hash of (const char *) absolute paths mapped
11323    to (svn_mergeinfo_t *) mergeinfo values for each working copy path with
11324    explicit mergeinfo in TARGET->abspath.  Actually we only need to know the
11325    paths, not the mergeinfo.
11326
11327    TARGET->loc.rev is the working revision the entire WC tree rooted at
11328    TARGET is at.
11329
11330    Populate *UNMERGED_TO_SOURCE_CATALOG with the mergeinfo describing what
11331    parts of TARGET->loc have not been merged to SOURCE_LOC, up to the
11332    youngest revision ever merged from the TARGET->abspath to the source if
11333    such exists, see doc string for find_unmerged_mergeinfo().
11334
11335    SOURCE_RA_SESSION is a session opened to the SOURCE_LOC
11336    and TARGET_RA_SESSION is open to TARGET->loc.url.
11337
11338    *LEFT_P, *MERGED_TO_SOURCE_CATALOG , and *UNMERGED_TO_SOURCE_CATALOG are
11339    allocated in RESULT_POOL.  SCRATCH_POOL is used for all temporary
11340    allocations. */
11341 static svn_error_t *
11342 calculate_left_hand_side(svn_client__pathrev_t **left_p,
11343                          svn_mergeinfo_catalog_t *merged_to_source_catalog,
11344                          svn_mergeinfo_catalog_t *unmerged_to_source_catalog,
11345                          const merge_target_t *target,
11346                          apr_hash_t *subtrees_with_mergeinfo,
11347                          const svn_client__pathrev_t *source_loc,
11348                          svn_ra_session_t *source_ra_session,
11349                          svn_ra_session_t *target_ra_session,
11350                          svn_client_ctx_t *ctx,
11351                          apr_pool_t *result_pool,
11352                          apr_pool_t *scratch_pool)
11353 {
11354   svn_mergeinfo_catalog_t mergeinfo_catalog, unmerged_catalog;
11355   apr_pool_t *iterpool = svn_pool_create(scratch_pool);
11356   apr_hash_index_t *hi;
11357   /* hash of paths mapped to arrays of svn_mergeinfo_t. */
11358   apr_hash_t *target_history_hash = apr_hash_make(scratch_pool);
11359   svn_revnum_t youngest_merged_rev;
11360   svn_client__pathrev_t *yc_ancestor;
11361
11362   assert(session_url_is(source_ra_session, source_loc->url, scratch_pool));
11363   assert(session_url_is(target_ra_session, target->loc.url, scratch_pool));
11364
11365   /* Initialize our return variables. */
11366   *left_p = NULL;
11367
11368   /* TARGET->abspath may not have explicit mergeinfo and thus may not be
11369      contained within SUBTREES_WITH_MERGEINFO.  If this is the case then
11370      add a dummy item for TARGET->abspath so we get its history (i.e. implicit
11371      mergeinfo) below.  */
11372   if (!svn_hash_gets(subtrees_with_mergeinfo, target->abspath))
11373     svn_hash_sets(subtrees_with_mergeinfo, target->abspath,
11374                   apr_hash_make(result_pool));
11375
11376   /* Get the history segments (as mergeinfo) for TARGET->abspath and any of
11377      its subtrees with explicit mergeinfo. */
11378   for (hi = apr_hash_first(scratch_pool, subtrees_with_mergeinfo);
11379        hi;
11380        hi = apr_hash_next(hi))
11381     {
11382       const char *local_abspath = apr_hash_this_key(hi);
11383       svn_client__pathrev_t *target_child;
11384       const char *repos_relpath;
11385       svn_mergeinfo_t target_history_as_mergeinfo;
11386
11387       svn_pool_clear(iterpool);
11388
11389       /* Convert the absolute path with mergeinfo on it to a path relative
11390          to the session root. */
11391       SVN_ERR(svn_wc__node_get_repos_info(NULL, &repos_relpath, NULL, NULL,
11392                                           ctx->wc_ctx, local_abspath,
11393                                           scratch_pool, iterpool));
11394       target_child = svn_client__pathrev_create_with_relpath(
11395                        target->loc.repos_root_url, target->loc.repos_uuid,
11396                        target->loc.rev, repos_relpath, iterpool);
11397       SVN_ERR(svn_client__get_history_as_mergeinfo(&target_history_as_mergeinfo,
11398                                                    NULL /* has_rev_zero_hist */,
11399                                                    target_child,
11400                                                    target->loc.rev,
11401                                                    SVN_INVALID_REVNUM,
11402                                                    target_ra_session,
11403                                                    ctx, scratch_pool));
11404
11405       svn_hash_sets(target_history_hash, repos_relpath,
11406                     target_history_as_mergeinfo);
11407     }
11408
11409   /* Check that SOURCE_LOC and TARGET->loc are
11410      actually related, we can't reintegrate if they are not.  Also
11411      get an initial value for the YCA revision number. */
11412   SVN_ERR(svn_client__get_youngest_common_ancestor(
11413               &yc_ancestor, source_loc, &target->loc, target_ra_session, ctx,
11414               iterpool, iterpool));
11415   if (! yc_ancestor)
11416     return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
11417                              _("'%s@%ld' must be ancestrally related to "
11418                                "'%s@%ld'"), source_loc->url, source_loc->rev,
11419                              target->loc.url, target->loc.rev);
11420
11421   /* If the source revision is the same as the youngest common
11422      revision, then there can't possibly be any unmerged revisions
11423      that we need to apply to target. */
11424   if (source_loc->rev == yc_ancestor->rev)
11425     {
11426       svn_pool_destroy(iterpool);
11427       return SVN_NO_ERROR;
11428     }
11429
11430   /* Get the mergeinfo from the source, including its descendants
11431      with differing explicit mergeinfo. */
11432   SVN_ERR(svn_client__get_repos_mergeinfo_catalog(
11433             &mergeinfo_catalog, source_ra_session,
11434             source_loc->url, source_loc->rev,
11435             svn_mergeinfo_inherited, FALSE /* squelch_incapable */,
11436             TRUE /* include_descendants */, iterpool, iterpool));
11437
11438   if (!mergeinfo_catalog)
11439     mergeinfo_catalog = apr_hash_make(iterpool);
11440
11441   *merged_to_source_catalog = svn_mergeinfo_catalog_dup(mergeinfo_catalog,
11442                                                         result_pool);
11443
11444   /* Filter the source's mergeinfo catalog so that we are left with
11445      mergeinfo that describes what has *not* previously been merged from
11446      TARGET->loc to SOURCE_LOC. */
11447   SVN_ERR(find_unmerged_mergeinfo(&unmerged_catalog,
11448                                   &youngest_merged_rev,
11449                                   yc_ancestor->rev,
11450                                   mergeinfo_catalog,
11451                                   target_history_hash,
11452                                   source_loc,
11453                                   target,
11454                                   source_ra_session,
11455                                   target_ra_session,
11456                                   ctx,
11457                                   iterpool, iterpool));
11458
11459   /* Simplify unmerged_catalog through elision then make a copy in POOL. */
11460   SVN_ERR(svn_client__elide_mergeinfo_catalog(unmerged_catalog,
11461                                               iterpool));
11462   *unmerged_to_source_catalog = svn_mergeinfo_catalog_dup(unmerged_catalog,
11463                                                           result_pool);
11464
11465   if (youngest_merged_rev == SVN_INVALID_REVNUM)
11466     {
11467       /* We never merged to the source.  Just return the branch point. */
11468       *left_p = svn_client__pathrev_dup(yc_ancestor, result_pool);
11469     }
11470   else
11471     {
11472       /* We've previously merged some or all of the target, up to
11473          youngest_merged_rev, to the source.  Set
11474          *LEFT_P to cover the youngest part of this range. */
11475       SVN_ERR(svn_client__repos_location(left_p, target_ra_session,
11476                                          &target->loc, youngest_merged_rev,
11477                                          ctx, result_pool, iterpool));
11478     }
11479
11480   svn_pool_destroy(iterpool);
11481   return SVN_NO_ERROR;
11482 }
11483
11484 /* Determine the URLs and revisions needed to perform a reintegrate merge
11485  * from SOURCE_LOC into the working copy at TARGET.
11486  *
11487  * SOURCE_RA_SESSION and TARGET_RA_SESSION are RA sessions opened to the
11488  * URLs of SOURCE_LOC and TARGET->loc respectively.
11489  *
11490  * Set *SOURCE_P to
11491  * the source-left and source-right locations of the required merge.  Set
11492  * *YC_ANCESTOR_P to the location of the youngest ancestor.
11493  * Any of these output pointers may be NULL if not wanted.
11494  *
11495  * See svn_client_find_reintegrate_merge() for other details.
11496  */
11497 static svn_error_t *
11498 find_reintegrate_merge(merge_source_t **source_p,
11499                        svn_client__pathrev_t **yc_ancestor_p,
11500                        svn_ra_session_t *source_ra_session,
11501                        const svn_client__pathrev_t *source_loc,
11502                        svn_ra_session_t *target_ra_session,
11503                        const merge_target_t *target,
11504                        svn_client_ctx_t *ctx,
11505                        apr_pool_t *result_pool,
11506                        apr_pool_t *scratch_pool)
11507 {
11508   svn_client__pathrev_t *yc_ancestor;
11509   svn_client__pathrev_t *loc1;
11510   merge_source_t source;
11511   svn_mergeinfo_catalog_t unmerged_to_source_mergeinfo_catalog;
11512   svn_mergeinfo_catalog_t merged_to_source_mergeinfo_catalog;
11513   svn_error_t *err;
11514   apr_hash_t *subtrees_with_mergeinfo;
11515
11516   assert(session_url_is(source_ra_session, source_loc->url, scratch_pool));
11517   assert(session_url_is(target_ra_session, target->loc.url, scratch_pool));
11518
11519   /* As the WC tree is "pure", use its last-updated-to revision as
11520      the default revision for the left side of our merge, since that's
11521      what the repository sub-tree is required to be up to date with
11522      (with regard to the WC). */
11523   /* ### Bogus/obsolete comment? */
11524
11525   /* Can't reintegrate to or from the root of the repository. */
11526   if (strcmp(source_loc->url, source_loc->repos_root_url) == 0
11527       || strcmp(target->loc.url, target->loc.repos_root_url) == 0)
11528     return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
11529                              _("Neither the reintegrate source nor target "
11530                                "can be the root of the repository"));
11531
11532   /* Find all the subtrees in TARGET_WCPATH that have explicit mergeinfo. */
11533   err = get_wc_explicit_mergeinfo_catalog(&subtrees_with_mergeinfo,
11534                                           target->abspath, svn_depth_infinity,
11535                                           ctx, scratch_pool, scratch_pool);
11536   /* Issue #3896: If invalid mergeinfo in the reintegrate target
11537      prevents us from proceeding, then raise the best error possible. */
11538   if (err && err->apr_err == SVN_ERR_CLIENT_INVALID_MERGEINFO_NO_MERGETRACKING)
11539     err = svn_error_quick_wrap(err, _("Reintegrate merge not possible"));
11540   SVN_ERR(err);
11541
11542   SVN_ERR(calculate_left_hand_side(&loc1,
11543                                    &merged_to_source_mergeinfo_catalog,
11544                                    &unmerged_to_source_mergeinfo_catalog,
11545                                    target,
11546                                    subtrees_with_mergeinfo,
11547                                    source_loc,
11548                                    source_ra_session,
11549                                    target_ra_session,
11550                                    ctx,
11551                                    scratch_pool, scratch_pool));
11552
11553   /* Did calculate_left_hand_side() decide that there was no merge to
11554      be performed here?  */
11555   if (! loc1)
11556     {
11557       if (source_p)
11558         *source_p = NULL;
11559       if (yc_ancestor_p)
11560         *yc_ancestor_p = NULL;
11561       return SVN_NO_ERROR;
11562     }
11563
11564   source.loc1 = loc1;
11565   source.loc2 = source_loc;
11566
11567   /* If the target was moved after the source was branched from it,
11568      it is possible that the left URL differs from the target's current
11569      URL.  If so, then adjust TARGET_RA_SESSION to point to the old URL. */
11570   if (strcmp(source.loc1->url, target->loc.url))
11571     SVN_ERR(svn_ra_reparent(target_ra_session, source.loc1->url, scratch_pool));
11572
11573   SVN_ERR(svn_client__get_youngest_common_ancestor(
11574             &yc_ancestor, source.loc2, source.loc1, target_ra_session,
11575             ctx, scratch_pool, scratch_pool));
11576
11577   if (! yc_ancestor)
11578     return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
11579                              _("'%s@%ld' must be ancestrally related to "
11580                                "'%s@%ld'"),
11581                              source.loc1->url, source.loc1->rev,
11582                              source.loc2->url, source.loc2->rev);
11583
11584   /* The source side of a reintegrate merge is not 'ancestral', except in
11585    * the degenerate case where source == YCA. */
11586   source.ancestral = (loc1->rev == yc_ancestor->rev);
11587
11588   if (source.loc1->rev > yc_ancestor->rev)
11589     {
11590       /* Have we actually merged anything to the source from the
11591          target?  If so, make sure we've merged a contiguous
11592          prefix. */
11593       svn_mergeinfo_catalog_t final_unmerged_catalog = apr_hash_make(scratch_pool);
11594
11595       SVN_ERR(find_unsynced_ranges(source_loc, &target->loc,
11596                                    unmerged_to_source_mergeinfo_catalog,
11597                                    merged_to_source_mergeinfo_catalog,
11598                                    final_unmerged_catalog,
11599                                    target_ra_session, scratch_pool,
11600                                    scratch_pool));
11601
11602       if (apr_hash_count(final_unmerged_catalog))
11603         {
11604           svn_string_t *source_mergeinfo_cat_string;
11605
11606           SVN_ERR(svn_mergeinfo__catalog_to_formatted_string(
11607             &source_mergeinfo_cat_string,
11608             final_unmerged_catalog,
11609             "  ", _("    Missing ranges: "), scratch_pool));
11610           return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE,
11611                                    NULL,
11612                                    _("Reintegrate can only be used if "
11613                                      "revisions %ld through %ld were "
11614                                      "previously merged from %s to the "
11615                                      "reintegrate source, but this is "
11616                                      "not the case:\n%s"),
11617                                    yc_ancestor->rev + 1, source.loc2->rev,
11618                                    target->loc.url,
11619                                    source_mergeinfo_cat_string->data);
11620         }
11621     }
11622
11623   /* Left side: trunk@youngest-trunk-rev-merged-to-branch-at-specified-peg-rev
11624    * Right side: branch@specified-peg-revision */
11625   if (source_p)
11626     *source_p = merge_source_dup(&source, result_pool);
11627
11628   if (yc_ancestor_p)
11629     *yc_ancestor_p = svn_client__pathrev_dup(yc_ancestor, result_pool);
11630   return SVN_NO_ERROR;
11631 }
11632
11633 /* Resolve the source and target locations and open RA sessions to them, and
11634  * perform some checks appropriate for a reintegrate merge.
11635  *
11636  * Set *SOURCE_RA_SESSION_P and *SOURCE_LOC_P to a new session and the
11637  * repository location of SOURCE_PATH_OR_URL at SOURCE_PEG_REVISION.  Set
11638  * *TARGET_RA_SESSION_P and *TARGET_P to a new session and the repository
11639  * location of the WC at TARGET_ABSPATH.
11640  *
11641  * Throw a SVN_ERR_CLIENT_UNRELATED_RESOURCES error if the target WC node is
11642  * a locally added node or if the source and target are not in the same
11643  * repository.  Throw a SVN_ERR_CLIENT_NOT_READY_TO_MERGE error if the
11644  * target WC is not at a single revision without switched subtrees and
11645  * without local mods.
11646  *
11647  * Allocate all the outputs in RESULT_POOL.
11648  */
11649 static svn_error_t *
11650 open_reintegrate_source_and_target(svn_ra_session_t **source_ra_session_p,
11651                                    svn_client__pathrev_t **source_loc_p,
11652                                    svn_ra_session_t **target_ra_session_p,
11653                                    merge_target_t **target_p,
11654                                    const char *source_path_or_url,
11655                                    const svn_opt_revision_t *source_peg_revision,
11656                                    const char *target_abspath,
11657                                    svn_client_ctx_t *ctx,
11658                                    apr_pool_t *result_pool,
11659                                    apr_pool_t *scratch_pool)
11660 {
11661   svn_client__pathrev_t *source_loc;
11662   merge_target_t *target;
11663
11664   /* Open the target WC.  A reintegrate merge requires the merge target to
11665    * reflect a subtree of the repository as found at a single revision. */
11666   SVN_ERR(open_target_wc(&target, target_abspath,
11667                          FALSE, FALSE, FALSE,
11668                          ctx, scratch_pool, scratch_pool));
11669   if (! target->loc.url)
11670     return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
11671                              _("Can't reintegrate into '%s' because it is "
11672                                "locally added and therefore not related to "
11673                                "the merge source"),
11674                              svn_dirent_local_style(target->abspath,
11675                                                     scratch_pool));
11676
11677   SVN_ERR(svn_client_open_ra_session2(target_ra_session_p,
11678                                       target->loc.url, target->abspath,
11679                                       ctx, result_pool, scratch_pool));
11680
11681   SVN_ERR(svn_client__ra_session_from_path2(
11682             source_ra_session_p, &source_loc,
11683             source_path_or_url, NULL, source_peg_revision, source_peg_revision,
11684             ctx, result_pool));
11685
11686   /* source_loc and target->loc are required to be in the same repository,
11687      as mergeinfo doesn't come into play for cross-repository merging. */
11688   SVN_ERR(check_same_repos(source_loc,
11689                            svn_dirent_local_style(source_path_or_url,
11690                                                   scratch_pool),
11691                            &target->loc,
11692                            svn_dirent_local_style(target->abspath,
11693                                                   scratch_pool),
11694                            TRUE /* strict_urls */, scratch_pool));
11695
11696   *source_loc_p = source_loc;
11697   *target_p = target;
11698   return SVN_NO_ERROR;
11699 }
11700
11701 /* The body of svn_client_merge_reintegrate(), which see for details. */
11702 static svn_error_t *
11703 merge_reintegrate_locked(conflict_report_t **conflict_report,
11704                          const char *source_path_or_url,
11705                          const svn_opt_revision_t *source_peg_revision,
11706                          const char *target_abspath,
11707                          svn_boolean_t diff_ignore_ancestry,
11708                          svn_boolean_t dry_run,
11709                          const apr_array_header_t *merge_options,
11710                          svn_client_ctx_t *ctx,
11711                          apr_pool_t *result_pool,
11712                          apr_pool_t *scratch_pool)
11713 {
11714   svn_ra_session_t *target_ra_session, *source_ra_session;
11715   merge_target_t *target;
11716   svn_client__pathrev_t *source_loc;
11717   merge_source_t *source;
11718   svn_client__pathrev_t *yc_ancestor;
11719   svn_boolean_t use_sleep = FALSE;
11720   svn_error_t *err;
11721
11722   SVN_ERR(open_reintegrate_source_and_target(
11723             &source_ra_session, &source_loc, &target_ra_session, &target,
11724             source_path_or_url, source_peg_revision, target_abspath,
11725             ctx, scratch_pool, scratch_pool));
11726
11727   SVN_ERR(find_reintegrate_merge(&source, &yc_ancestor,
11728                                  source_ra_session, source_loc,
11729                                  target_ra_session, target,
11730                                  ctx, scratch_pool, scratch_pool));
11731
11732   if (! source)
11733     {
11734       *conflict_report = NULL;
11735       return SVN_NO_ERROR;
11736     }
11737
11738   /* Do the real merge! */
11739   /* ### TODO(reint): Make sure that one isn't the same line ancestor
11740      ### of the other (what's erroneously referred to as "ancestrally
11741      ### related" in this source file).  For now, we just say the source
11742      ### isn't "ancestral" even if it is (in the degenerate case where
11743      ### source-left equals YCA). */
11744   source->ancestral = FALSE;
11745   err = merge_cousins_and_supplement_mergeinfo(conflict_report,
11746                                                &use_sleep,
11747                                                target,
11748                                                target_ra_session,
11749                                                source_ra_session,
11750                                                source, yc_ancestor,
11751                                                TRUE /* same_repos */,
11752                                                svn_depth_infinity,
11753                                                diff_ignore_ancestry,
11754                                                FALSE /* force_delete */,
11755                                                FALSE /* record_only */,
11756                                                dry_run,
11757                                                merge_options,
11758                                                ctx,
11759                                                result_pool, scratch_pool);
11760
11761   if (use_sleep)
11762     svn_io_sleep_for_timestamps(target_abspath, scratch_pool);
11763
11764   SVN_ERR(err);
11765   return SVN_NO_ERROR;
11766 }
11767
11768 svn_error_t *
11769 svn_client_merge_reintegrate(const char *source_path_or_url,
11770                              const svn_opt_revision_t *source_peg_revision,
11771                              const char *target_wcpath,
11772                              svn_boolean_t dry_run,
11773                              const apr_array_header_t *merge_options,
11774                              svn_client_ctx_t *ctx,
11775                              apr_pool_t *pool)
11776 {
11777   const char *target_abspath, *lock_abspath;
11778   conflict_report_t *conflict_report;
11779
11780   SVN_ERR(get_target_and_lock_abspath(&target_abspath, &lock_abspath,
11781                                       target_wcpath, ctx, pool));
11782
11783   if (!dry_run)
11784     SVN_WC__CALL_WITH_WRITE_LOCK(
11785       merge_reintegrate_locked(&conflict_report,
11786                                source_path_or_url, source_peg_revision,
11787                                target_abspath,
11788                                FALSE /*diff_ignore_ancestry*/,
11789                                dry_run, merge_options, ctx, pool, pool),
11790       ctx->wc_ctx, lock_abspath, FALSE /* lock_anchor */, pool);
11791   else
11792     SVN_ERR(merge_reintegrate_locked(&conflict_report,
11793                                      source_path_or_url, source_peg_revision,
11794                                      target_abspath,
11795                                      FALSE /*diff_ignore_ancestry*/,
11796                                      dry_run, merge_options, ctx, pool, pool));
11797
11798   SVN_ERR(make_merge_conflict_error(conflict_report, pool));
11799   return SVN_NO_ERROR;
11800 }
11801
11802
11803 /* The body of svn_client_merge_peg5(), which see for details.
11804  *
11805  * IGNORE_MERGEINFO and DIFF_IGNORE_ANCESTRY are as in do_merge().
11806  */
11807 static svn_error_t *
11808 merge_peg_locked(conflict_report_t **conflict_report,
11809                  const char *source_path_or_url,
11810                  const svn_opt_revision_t *source_peg_revision,
11811                  const svn_rangelist_t *ranges_to_merge,
11812                  const char *target_abspath,
11813                  svn_depth_t depth,
11814                  svn_boolean_t ignore_mergeinfo,
11815                  svn_boolean_t diff_ignore_ancestry,
11816                  svn_boolean_t force_delete,
11817                  svn_boolean_t record_only,
11818                  svn_boolean_t dry_run,
11819                  svn_boolean_t allow_mixed_rev,
11820                  const apr_array_header_t *merge_options,
11821                  svn_client_ctx_t *ctx,
11822                  apr_pool_t *result_pool,
11823                  apr_pool_t *scratch_pool)
11824 {
11825   merge_target_t *target;
11826   svn_client__pathrev_t *source_loc;
11827   apr_array_header_t *merge_sources;
11828   svn_ra_session_t *ra_session;
11829   apr_pool_t *sesspool;
11830   svn_boolean_t use_sleep = FALSE;
11831   svn_error_t *err;
11832   svn_boolean_t same_repos;
11833
11834   SVN_ERR_ASSERT(svn_dirent_is_absolute(target_abspath));
11835
11836   SVN_ERR(open_target_wc(&target, target_abspath,
11837                          allow_mixed_rev, TRUE, TRUE,
11838                          ctx, scratch_pool, scratch_pool));
11839
11840   /* Create a short lived session pool */
11841   sesspool = svn_pool_create(scratch_pool);
11842
11843   /* Open an RA session to our source URL, and determine its root URL. */
11844   SVN_ERR(svn_client__ra_session_from_path2(
11845             &ra_session, &source_loc,
11846             source_path_or_url, NULL, source_peg_revision, source_peg_revision,
11847             ctx, sesspool));
11848
11849   /* Normalize our merge sources. */
11850   SVN_ERR(normalize_merge_sources(&merge_sources, source_path_or_url,
11851                                   source_loc,
11852                                   ranges_to_merge, ra_session, ctx,
11853                                   scratch_pool, scratch_pool));
11854
11855   /* Check for same_repos. */
11856   same_repos = is_same_repos(&target->loc, source_loc, TRUE /* strict_urls */);
11857
11858   /* Do the real merge!  (We say with confidence that our merge
11859      sources are both ancestral and related.) */
11860   err = do_merge(NULL, NULL, conflict_report, &use_sleep,
11861                  merge_sources, target, ra_session,
11862                  TRUE /*sources_related*/, same_repos, ignore_mergeinfo,
11863                  diff_ignore_ancestry, force_delete, dry_run,
11864                  record_only, NULL, FALSE, FALSE, depth, merge_options,
11865                  ctx, result_pool, scratch_pool);
11866
11867   /* We're done with our RA session. */
11868   svn_pool_destroy(sesspool);
11869
11870   if (use_sleep)
11871     svn_io_sleep_for_timestamps(target_abspath, scratch_pool);
11872
11873   SVN_ERR(err);
11874   return SVN_NO_ERROR;
11875 }
11876
11877 /* Details of an automatic merge. */
11878 typedef struct automatic_merge_t
11879 {
11880   svn_client__pathrev_t *yca, *base, *right, *target;
11881   svn_boolean_t is_reintegrate_like;
11882   svn_boolean_t allow_mixed_rev, allow_local_mods, allow_switched_subtrees;
11883 } automatic_merge_t;
11884
11885 static svn_error_t *
11886 client_find_automatic_merge(automatic_merge_t **merge_p,
11887                             const char *source_path_or_url,
11888                             const svn_opt_revision_t *source_revision,
11889                             const char *target_abspath,
11890                             svn_boolean_t allow_mixed_rev,
11891                             svn_boolean_t allow_local_mods,
11892                             svn_boolean_t allow_switched_subtrees,
11893                             svn_client_ctx_t *ctx,
11894                             apr_pool_t *result_pool,
11895                             apr_pool_t *scratch_pool);
11896
11897 static svn_error_t *
11898 do_automatic_merge_locked(conflict_report_t **conflict_report,
11899                           const automatic_merge_t *merge,
11900                           const char *target_abspath,
11901                           svn_depth_t depth,
11902                           svn_boolean_t diff_ignore_ancestry,
11903                           svn_boolean_t force_delete,
11904                           svn_boolean_t record_only,
11905                           svn_boolean_t dry_run,
11906                           const apr_array_header_t *merge_options,
11907                           svn_client_ctx_t *ctx,
11908                           apr_pool_t *result_pool,
11909                           apr_pool_t *scratch_pool);
11910
11911 svn_error_t *
11912 svn_client_merge_peg5(const char *source_path_or_url,
11913                       const apr_array_header_t *ranges_to_merge,
11914                       const svn_opt_revision_t *source_peg_revision,
11915                       const char *target_wcpath,
11916                       svn_depth_t depth,
11917                       svn_boolean_t ignore_mergeinfo,
11918                       svn_boolean_t diff_ignore_ancestry,
11919                       svn_boolean_t force_delete,
11920                       svn_boolean_t record_only,
11921                       svn_boolean_t dry_run,
11922                       svn_boolean_t allow_mixed_rev,
11923                       const apr_array_header_t *merge_options,
11924                       svn_client_ctx_t *ctx,
11925                       apr_pool_t *pool)
11926 {
11927   const char *target_abspath, *lock_abspath;
11928   conflict_report_t *conflict_report;
11929
11930   /* No ranges to merge?  No problem. */
11931   if (ranges_to_merge != NULL && ranges_to_merge->nelts == 0)
11932     return SVN_NO_ERROR;
11933
11934   SVN_ERR(get_target_and_lock_abspath(&target_abspath, &lock_abspath,
11935                                       target_wcpath, ctx, pool));
11936
11937   /* Do an automatic merge if no revision ranges are specified. */
11938   if (ranges_to_merge == NULL)
11939     {
11940       automatic_merge_t *merge;
11941
11942       if (ignore_mergeinfo)
11943         return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
11944                                 _("Cannot merge automatically while "
11945                                   "ignoring mergeinfo"));
11946
11947       /* Find the details of the merge needed. */
11948       SVN_ERR(client_find_automatic_merge(
11949                                     &merge,
11950                                     source_path_or_url, source_peg_revision,
11951                                     target_abspath,
11952                                     allow_mixed_rev,
11953                                     TRUE /*allow_local_mods*/,
11954                                     TRUE /*allow_switched_subtrees*/,
11955                                     ctx, pool, pool));
11956
11957       if (!dry_run)
11958         SVN_WC__CALL_WITH_WRITE_LOCK(
11959           do_automatic_merge_locked(&conflict_report,
11960                                     merge,
11961                                     target_abspath, depth,
11962                                     diff_ignore_ancestry,
11963                                     force_delete, record_only, dry_run,
11964                                     merge_options, ctx, pool, pool),
11965           ctx->wc_ctx, lock_abspath, FALSE /* lock_anchor */, pool);
11966       else
11967         SVN_ERR(do_automatic_merge_locked(&conflict_report,
11968                                     merge,
11969                                     target_abspath, depth,
11970                                     diff_ignore_ancestry,
11971                                     force_delete, record_only, dry_run,
11972                                     merge_options, ctx, pool, pool));
11973     }
11974   else if (!dry_run)
11975     SVN_WC__CALL_WITH_WRITE_LOCK(
11976       merge_peg_locked(&conflict_report,
11977                        source_path_or_url, source_peg_revision,
11978                        ranges_to_merge,
11979                        target_abspath, depth, ignore_mergeinfo,
11980                        diff_ignore_ancestry,
11981                        force_delete, record_only, dry_run,
11982                        allow_mixed_rev, merge_options, ctx, pool, pool),
11983       ctx->wc_ctx, lock_abspath, FALSE /* lock_anchor */, pool);
11984   else
11985     SVN_ERR(merge_peg_locked(&conflict_report,
11986                        source_path_or_url, source_peg_revision,
11987                        ranges_to_merge,
11988                        target_abspath, depth, ignore_mergeinfo,
11989                        diff_ignore_ancestry,
11990                        force_delete, record_only, dry_run,
11991                        allow_mixed_rev, merge_options, ctx, pool, pool));
11992
11993   SVN_ERR(make_merge_conflict_error(conflict_report, pool));
11994   return SVN_NO_ERROR;
11995 }
11996
11997
11998 /* The location-history of a branch.
11999  *
12000  * This structure holds the set of path-revisions occupied by a branch,
12001  * from an externally chosen 'tip' location back to its origin.  The
12002  * 'tip' location is the youngest location that we are considering on
12003  * the branch. */
12004 typedef struct branch_history_t
12005 {
12006   /* The tip location of the branch.  That is, the youngest location that's
12007    * in the repository and that we're considering.  If we're considering a
12008    * target branch right up to an uncommitted WC, then this is the WC base
12009    * (pristine) location. */
12010   svn_client__pathrev_t *tip;
12011   /* The location-segment history, as mergeinfo. */
12012   svn_mergeinfo_t history;
12013   /* Whether the location-segment history reached as far as (necessarily
12014      the root path in) revision 0 -- a fact that can't be represented as
12015      mergeinfo. */
12016   svn_boolean_t has_r0_history;
12017 } branch_history_t;
12018
12019 /* Return the location on BRANCH_HISTORY at revision REV, or NULL if none. */
12020 static svn_client__pathrev_t *
12021 location_on_branch_at_rev(const branch_history_t *branch_history,
12022                           svn_revnum_t rev,
12023                           apr_pool_t *result_pool,
12024                           apr_pool_t *scratch_pool)
12025 {
12026   apr_hash_index_t *hi;
12027
12028   for (hi = apr_hash_first(scratch_pool, branch_history->history); hi;
12029        hi = apr_hash_next(hi))
12030     {
12031       const char *fspath = apr_hash_this_key(hi);
12032       svn_rangelist_t *rangelist = apr_hash_this_val(hi);
12033       int i;
12034
12035       for (i = 0; i < rangelist->nelts; i++)
12036         {
12037           svn_merge_range_t *r = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *);
12038           if (r->start < rev && rev <= r->end)
12039             {
12040               return svn_client__pathrev_create_with_relpath(
12041                        branch_history->tip->repos_root_url,
12042                        branch_history->tip->repos_uuid,
12043                        rev, fspath + 1, result_pool);
12044             }
12045         }
12046     }
12047   return NULL;
12048 }
12049
12050 /* */
12051 typedef struct source_and_target_t
12052 {
12053   svn_client__pathrev_t *source;
12054   svn_ra_session_t *source_ra_session;
12055   branch_history_t source_branch;
12056
12057   merge_target_t *target;
12058   svn_ra_session_t *target_ra_session;
12059   branch_history_t target_branch;
12060
12061   /* Repos location of the youngest common ancestor of SOURCE and TARGET. */
12062   svn_client__pathrev_t *yca;
12063 } source_and_target_t;
12064
12065 /* Set *INTERSECTION_P to the intersection of BRANCH_HISTORY with the
12066  * revision range OLDEST_REV to YOUNGEST_REV (inclusive).
12067  *
12068  * If the intersection is empty, the result will be a branch history object
12069  * containing an empty (not null) history.
12070  *
12071  * ### The 'tip' of the result is currently unchanged.
12072  */
12073 static svn_error_t *
12074 branch_history_intersect_range(branch_history_t **intersection_p,
12075                                const branch_history_t *branch_history,
12076                                svn_revnum_t oldest_rev,
12077                                svn_revnum_t youngest_rev,
12078                                apr_pool_t *result_pool,
12079                                apr_pool_t *scratch_pool)
12080 {
12081   branch_history_t *result = apr_palloc(result_pool, sizeof(*result));
12082
12083   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(oldest_rev));
12084   SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(youngest_rev));
12085   SVN_ERR_ASSERT(oldest_rev >= 1);
12086   /* Allow a just-empty range (oldest = youngest + 1) but not an
12087    * arbitrary reverse range (such as oldest = youngest + 2). */
12088   SVN_ERR_ASSERT(oldest_rev <= youngest_rev + 1);
12089
12090   if (oldest_rev <= youngest_rev)
12091     {
12092       SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
12093                 &result->history, branch_history->history,
12094                 youngest_rev, oldest_rev - 1, TRUE /* include_range */,
12095                 result_pool, scratch_pool));
12096       result->history = svn_mergeinfo_dup(result->history, result_pool);
12097     }
12098   else
12099     {
12100       result->history = apr_hash_make(result_pool);
12101     }
12102   result->has_r0_history = FALSE;
12103
12104   /* ### TODO: Set RESULT->tip to the tip of the intersection. */
12105   result->tip = svn_client__pathrev_dup(branch_history->tip, result_pool);
12106
12107   *intersection_p = result;
12108   return SVN_NO_ERROR;
12109 }
12110
12111 /* Set *OLDEST_P and *YOUNGEST_P to the oldest and youngest locations
12112  * (inclusive) along BRANCH.  OLDEST_P and/or YOUNGEST_P may be NULL if not
12113  * wanted.
12114  */
12115 static svn_error_t *
12116 branch_history_get_endpoints(svn_client__pathrev_t **oldest_p,
12117                              svn_client__pathrev_t **youngest_p,
12118                              const branch_history_t *branch,
12119                              apr_pool_t *result_pool,
12120                              apr_pool_t *scratch_pool)
12121 {
12122   svn_revnum_t youngest_rev, oldest_rev;
12123
12124   SVN_ERR(svn_mergeinfo__get_range_endpoints(
12125             &youngest_rev, &oldest_rev,
12126             branch->history, scratch_pool));
12127   if (oldest_p)
12128     *oldest_p = location_on_branch_at_rev(
12129                   branch, oldest_rev + 1, result_pool, scratch_pool);
12130   if (youngest_p)
12131     *youngest_p = location_on_branch_at_rev(
12132                     branch, youngest_rev, result_pool, scratch_pool);
12133   return SVN_NO_ERROR;
12134 }
12135
12136 /* Implements the svn_log_entry_receiver_t interface.
12137
12138   Set *BATON to LOG_ENTRY->revision and return SVN_ERR_CEASE_INVOCATION. */
12139 static svn_error_t *
12140 operative_rev_receiver(void *baton,
12141                        svn_log_entry_t *log_entry,
12142                        apr_pool_t *pool)
12143 {
12144   svn_revnum_t *operative_rev = baton;
12145
12146   *operative_rev = log_entry->revision;
12147
12148   /* We've found the youngest merged or oldest eligible revision, so
12149      we're done...
12150
12151      ...but wait, shouldn't we care if LOG_ENTRY->NON_INHERITABLE is
12152      true?  Because if it is, then LOG_ENTRY->REVISION is only
12153      partially merged/elgibile!  And our only caller,
12154      find_last_merged_location (via short_circuit_mergeinfo_log) is
12155      interested in *fully* merged revisions.  That's all true, but if
12156      find_last_merged_location() finds the youngest merged revision it
12157      will also check for the oldest eligible revision.  So in the case
12158      the youngest merged rev is non-inheritable, the *same* non-inheritable
12159      rev will be found as the oldest eligible rev -- and
12160      find_last_merged_location() handles that situation. */
12161   return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
12162 }
12163
12164 /* Wrapper around svn_client__mergeinfo_log. All arguments are as per
12165    that private API.  The discover_changed_paths, depth, and revprops args to
12166    svn_client__mergeinfo_log are always TRUE, svn_depth_infinity_t,
12167    and empty array respectively.
12168
12169    If RECEIVER raises a SVN_ERR_CEASE_INVOCATION error, but still sets
12170    *REVISION to a valid revnum, then clear the error.  Otherwise return
12171    any error. */
12172 static svn_error_t*
12173 short_circuit_mergeinfo_log(svn_mergeinfo_catalog_t *target_mergeinfo_cat,
12174                             svn_boolean_t finding_merged,
12175                             const char *target_path_or_url,
12176                             const svn_opt_revision_t *target_peg_revision,
12177                             const char *source_path_or_url,
12178                             const svn_opt_revision_t *source_peg_revision,
12179                             const svn_opt_revision_t *source_start_revision,
12180                             const svn_opt_revision_t *source_end_revision,
12181                             svn_log_entry_receiver_t receiver,
12182                             svn_revnum_t *revision,
12183                             svn_client_ctx_t *ctx,
12184                             svn_ra_session_t *ra_session,
12185                             apr_pool_t *result_pool,
12186                             apr_pool_t *scratch_pool)
12187 {
12188   apr_array_header_t *revprops;
12189   svn_error_t *err;
12190   const char *session_url;
12191
12192   SVN_ERR(svn_ra_get_session_url(ra_session, &session_url, scratch_pool));
12193
12194   revprops = apr_array_make(scratch_pool, 0, sizeof(const char *));
12195   err = svn_client__mergeinfo_log(finding_merged,
12196                                   target_path_or_url,
12197                                   target_peg_revision,
12198                                   target_mergeinfo_cat,
12199                                   source_path_or_url,
12200                                   source_peg_revision,
12201                                   source_start_revision,
12202                                   source_end_revision,
12203                                   receiver, revision,
12204                                   TRUE, svn_depth_infinity,
12205                                   revprops, ctx, ra_session,
12206                                   result_pool, scratch_pool);
12207
12208   err = svn_error_compose_create(
12209                   err,
12210                   svn_ra_reparent(ra_session, session_url, scratch_pool));
12211
12212   if (err)
12213     {
12214       /* We expect RECEIVER to short-circuit the (potentially expensive) log
12215          by raising an SVN_ERR_CEASE_INVOCATION -- see operative_rev_receiver.
12216          So we can ignore that error, but only as long as we actually found a
12217          valid revision. */
12218       if (SVN_IS_VALID_REVNUM(*revision)
12219           && err->apr_err == SVN_ERR_CEASE_INVOCATION)
12220         {
12221           svn_error_clear(err);
12222           err = NULL;
12223         }
12224       else
12225         {
12226           return svn_error_trace(err);
12227         }
12228     }
12229   return SVN_NO_ERROR;
12230 }
12231
12232 /* Set *BASE_P to the last location on SOURCE_BRANCH such that all changes
12233  * on SOURCE_BRANCH after YCA up to and including *BASE_P have already
12234  * been fully merged into TARGET.
12235  *
12236  *               *BASE_P       TIP
12237  *          o-------o-----------o--- SOURCE_BRANCH
12238  *         /         \
12239  *   -----o     prev. \
12240  *     YCA \    merges \
12241  *          o-----------o----------- TARGET branch
12242  *
12243  * In terms of mergeinfo:
12244  *
12245  *     Source     a--...                     o=change, -=no-op revision
12246  *       branch  /   \
12247  *     YCA -->  o     a---o---o---o---o---   d=delete, a=add-as-a-copy
12248  *
12249  *     Eligible -.eee.eeeeeeeeeeeeeeeeeeee   .=not a source branch location
12250  *
12251  *     Tgt-mi   -.mmm.mm-mm-------m-------   m=merged to root of TARGET or
12252  *                                           subtree of TARGET with no
12253  *                                           operative changes outside of that
12254  *                                           subtree, -=not merged
12255  *
12256  *     Eligible -.---.--e--eeeeeee-eeeeeee
12257  *
12258  *     Next     --------^-----------------   BASE is just before here.
12259  *
12260  *             /         \
12261  *       -----o     prev. \
12262  *         YCA \    merges \
12263  *              o-----------o-------------
12264  *
12265  * If no revisions from SOURCE_BRANCH have been completely merged to TARGET,
12266  * then set *BASE_P to the YCA.
12267  */
12268 static svn_error_t *
12269 find_last_merged_location(svn_client__pathrev_t **base_p,
12270                           svn_client__pathrev_t *yca,
12271                           const branch_history_t *source_branch,
12272                           svn_client__pathrev_t *target,
12273                           svn_client_ctx_t *ctx,
12274                           svn_ra_session_t *ra_session,
12275                           apr_pool_t *result_pool,
12276                           apr_pool_t *scratch_pool)
12277 {
12278   svn_opt_revision_t source_peg_rev, source_start_rev, source_end_rev,
12279     target_opt_rev;
12280   svn_revnum_t youngest_merged_rev = SVN_INVALID_REVNUM;
12281   svn_mergeinfo_catalog_t target_mergeinfo_cat = NULL;
12282
12283   source_peg_rev.kind = svn_opt_revision_number;
12284   source_peg_rev.value.number = source_branch->tip->rev;
12285   source_start_rev.kind = svn_opt_revision_number;
12286   source_start_rev.value.number = yca->rev;
12287   source_end_rev.kind = svn_opt_revision_number;
12288   source_end_rev.value.number = source_branch->tip->rev;
12289   target_opt_rev.kind = svn_opt_revision_number;
12290   target_opt_rev.value.number = target->rev;
12291
12292   /* Find the youngest revision fully merged from SOURCE_BRANCH to TARGET,
12293      if such a revision exists. */
12294   SVN_ERR(short_circuit_mergeinfo_log(&target_mergeinfo_cat,
12295                                       TRUE, /* Find merged */
12296                                       target->url, &target_opt_rev,
12297                                       source_branch->tip->url,
12298                                       &source_peg_rev,
12299                                       &source_end_rev, &source_start_rev,
12300                                       operative_rev_receiver,
12301                                       &youngest_merged_rev,
12302                                       ctx, ra_session,
12303                                       result_pool, scratch_pool));
12304
12305   if (!SVN_IS_VALID_REVNUM(youngest_merged_rev))
12306     {
12307       /* No revisions have been completely merged from SOURCE_BRANCH to
12308          TARGET so the base for the next merge is the YCA. */
12309       *base_p = yca;
12310     }
12311   else
12312     {
12313       /* One or more revisions have already been completely merged from
12314          SOURCE_BRANCH to TARGET, now find the oldest revision, older
12315          than the youngest merged revision, which is still eligible to
12316          be merged, if such exists. */
12317       branch_history_t *contiguous_source;
12318       svn_revnum_t base_rev;
12319       svn_revnum_t oldest_eligible_rev = SVN_INVALID_REVNUM;
12320
12321       /* If the only revisions eligible are younger than the youngest merged
12322          revision we can simply assume that the youngest eligible revision
12323          is the youngest merged revision.  Obviously this may not be true!
12324          The revisions between the youngest merged revision and the tip of
12325          the branch may have several inoperative revisions -- they may *all*
12326          be inoperative revisions!  But for the purpose of this function
12327          (i.e. finding the youngest revision after the YCA where all revs have
12328          been merged) that doesn't matter. */
12329       source_end_rev.value.number = youngest_merged_rev;
12330       SVN_ERR(short_circuit_mergeinfo_log(&target_mergeinfo_cat,
12331                                           FALSE, /* Find eligible */
12332                                           target->url, &target_opt_rev,
12333                                           source_branch->tip->url,
12334                                           &source_peg_rev,
12335                                           &source_start_rev, &source_end_rev,
12336                                           operative_rev_receiver,
12337                                           &oldest_eligible_rev,
12338                                           ctx, ra_session,
12339                                           scratch_pool, scratch_pool));
12340
12341       /* If there are revisions eligible for merging, use the oldest one
12342          to calculate the base.  Otherwise there are no operative revisions
12343          to merge and we can simple set the base to the youngest revision
12344          already merged. */
12345       if (SVN_IS_VALID_REVNUM(oldest_eligible_rev))
12346         base_rev = oldest_eligible_rev - 1;
12347       else
12348         base_rev = youngest_merged_rev;
12349
12350       /* Find the branch location just before the oldest eligible rev.
12351          (We can't just use the base revs calculated above because the branch
12352          might have a gap there.) */
12353       SVN_ERR(branch_history_intersect_range(&contiguous_source,
12354                                              source_branch, yca->rev,
12355                                              base_rev,
12356                                              scratch_pool, scratch_pool));
12357       SVN_ERR(branch_history_get_endpoints(NULL, base_p, contiguous_source,
12358                                            result_pool, scratch_pool));
12359     }
12360
12361   return SVN_NO_ERROR;
12362 }
12363
12364 /* Find a merge base location on the target branch, like in a sync
12365  * merge.
12366  *
12367  *                BASE          S_T->source
12368  *          o-------o-----------o---
12369  *         /         \           \
12370  *   -----o     prev. \           \  this
12371  *     YCA \    merge  \           \ merge
12372  *          o-----------o-----------o
12373  *                                  S_T->target
12374  *
12375  * Set *BASE_P to BASE, the youngest location in the history of S_T->source
12376  * (at or after the YCA) at which all revisions up to BASE are effectively
12377  * merged into S_T->target.
12378  *
12379  * If no locations on the history of S_T->source are effectively merged to
12380  * S_T->target, set *BASE_P to the YCA.
12381  */
12382 static svn_error_t *
12383 find_base_on_source(svn_client__pathrev_t **base_p,
12384                     source_and_target_t *s_t,
12385                     svn_client_ctx_t *ctx,
12386                     apr_pool_t *result_pool,
12387                     apr_pool_t *scratch_pool)
12388 {
12389   SVN_ERR(find_last_merged_location(base_p,
12390                                     s_t->yca,
12391                                     &s_t->source_branch,
12392                                     s_t->target_branch.tip,
12393                                     ctx,
12394                                     s_t->source_ra_session,
12395                                     result_pool, scratch_pool));
12396   return SVN_NO_ERROR;
12397 }
12398
12399 /* Find a merge base location on the target branch, like in a reintegrate
12400  * merge.
12401  *
12402  *                              S_T->source
12403  *          o-----------o-------o---
12404  *         /    prev.  /         \
12405  *   -----o     merge /           \  this
12406  *     YCA \         /             \ merge
12407  *          o-------o---------------o
12408  *                BASE              S_T->target
12409  *
12410  * Set *BASE_P to BASE, the youngest location in the history of S_T->target
12411  * (at or after the YCA) at which all revisions up to BASE are effectively
12412  * merged into S_T->source.
12413  *
12414  * If no locations on the history of S_T->target are effectively merged to
12415  * S_T->source, set *BASE_P to the YCA.
12416  */
12417 static svn_error_t *
12418 find_base_on_target(svn_client__pathrev_t **base_p,
12419                     source_and_target_t *s_t,
12420                     svn_client_ctx_t *ctx,
12421                     apr_pool_t *result_pool,
12422                     apr_pool_t *scratch_pool)
12423 {
12424   SVN_ERR(find_last_merged_location(base_p,
12425                                     s_t->yca,
12426                                     &s_t->target_branch,
12427                                     s_t->source,
12428                                     ctx,
12429                                     s_t->target_ra_session,
12430                                     result_pool, scratch_pool));
12431
12432   return SVN_NO_ERROR;
12433 }
12434
12435 /* Find the last point at which the branch at S_T->source was completely
12436  * merged to the branch at S_T->target or vice-versa.
12437  *
12438  * Fill in S_T->source_branch and S_T->target_branch and S_T->yca.
12439  * Set *BASE_P to the merge base.  Set *IS_REINTEGRATE_LIKE to true if
12440  * an automatic merge from source to target would be a reintegration
12441  * merge: that is, if the last automatic merge was in the opposite
12442  * direction; or to false otherwise.
12443  *
12444  * If there is no youngest common ancestor, throw an error.
12445  */
12446 static svn_error_t *
12447 find_automatic_merge(svn_client__pathrev_t **base_p,
12448                      svn_boolean_t *is_reintegrate_like,
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_client__pathrev_t *base_on_source, *base_on_target;
12455
12456   /* Get the location-history of each branch. */
12457   s_t->source_branch.tip = s_t->source;
12458   SVN_ERR(svn_client__get_history_as_mergeinfo(
12459             &s_t->source_branch.history, &s_t->source_branch.has_r0_history,
12460             s_t->source, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
12461             s_t->source_ra_session, ctx, scratch_pool));
12462   s_t->target_branch.tip = &s_t->target->loc;
12463   SVN_ERR(svn_client__get_history_as_mergeinfo(
12464             &s_t->target_branch.history, &s_t->target_branch.has_r0_history,
12465             &s_t->target->loc, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM,
12466             s_t->target_ra_session, ctx, scratch_pool));
12467
12468   SVN_ERR(svn_client__calc_youngest_common_ancestor(
12469             &s_t->yca, s_t->source, s_t->source_branch.history,
12470             s_t->source_branch.has_r0_history,
12471             &s_t->target->loc, s_t->target_branch.history,
12472             s_t->target_branch.has_r0_history,
12473             result_pool, scratch_pool));
12474
12475   if (! s_t->yca)
12476     return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
12477                              _("'%s@%ld' must be ancestrally related to "
12478                                "'%s@%ld'"),
12479                              s_t->source->url, s_t->source->rev,
12480                              s_t->target->loc.url, s_t->target->loc.rev);
12481
12482   /* Find the latest revision of A synced to B and the latest
12483    * revision of B synced to A.
12484    *
12485    *   base_on_source = youngest_complete_synced_point(source, target)
12486    *   base_on_target = youngest_complete_synced_point(target, source)
12487    */
12488   SVN_ERR(find_base_on_source(&base_on_source, s_t,
12489                               ctx, scratch_pool, scratch_pool));
12490   SVN_ERR(find_base_on_target(&base_on_target, s_t,
12491                               ctx, scratch_pool, scratch_pool));
12492
12493   /* Choose a base. */
12494   if (base_on_source->rev >= base_on_target->rev)
12495     {
12496       *base_p = base_on_source;
12497       *is_reintegrate_like = FALSE;
12498     }
12499   else
12500     {
12501       *base_p = base_on_target;
12502       *is_reintegrate_like = TRUE;
12503     }
12504
12505   return SVN_NO_ERROR;
12506 }
12507
12508 /** Find out what kind of automatic merge would be needed, when the target
12509  * is only known as a repository location rather than a WC.
12510  *
12511  * Like find_automatic_merge() except that the target is
12512  * specified by @a target_path_or_url at @a target_revision, which must
12513  * refer to a repository location, instead of by a WC path argument.
12514  *
12515  * Set *MERGE_P to a new structure with all fields filled in except the
12516  * 'allow_*' flags.
12517  */
12518 static svn_error_t *
12519 find_automatic_merge_no_wc(automatic_merge_t **merge_p,
12520                            const char *source_path_or_url,
12521                            const svn_opt_revision_t *source_revision,
12522                            const char *target_path_or_url,
12523                            const svn_opt_revision_t *target_revision,
12524                            svn_client_ctx_t *ctx,
12525                            apr_pool_t *result_pool,
12526                            apr_pool_t *scratch_pool)
12527 {
12528   source_and_target_t *s_t = apr_palloc(scratch_pool, sizeof(*s_t));
12529   svn_client__pathrev_t *target_loc;
12530   automatic_merge_t *merge = apr_palloc(result_pool, sizeof(*merge));
12531
12532   /* Source */
12533   SVN_ERR(svn_client__ra_session_from_path2(
12534             &s_t->source_ra_session, &s_t->source,
12535             source_path_or_url, NULL, source_revision, source_revision,
12536             ctx, result_pool));
12537
12538   /* Target */
12539   SVN_ERR(svn_client__ra_session_from_path2(
12540             &s_t->target_ra_session, &target_loc,
12541             target_path_or_url, NULL, target_revision, target_revision,
12542             ctx, result_pool));
12543   s_t->target = apr_palloc(scratch_pool, sizeof(*s_t->target));
12544   s_t->target->abspath = NULL;  /* indicate the target is not a WC */
12545   s_t->target->loc = *target_loc;
12546
12547   SVN_ERR(find_automatic_merge(&merge->base, &merge->is_reintegrate_like, s_t,
12548                                ctx, result_pool, scratch_pool));
12549
12550   merge->right = s_t->source;
12551   merge->target = &s_t->target->loc;
12552   merge->yca = s_t->yca;
12553   *merge_p = merge;
12554
12555   return SVN_NO_ERROR;
12556 }
12557
12558 /* Find the information needed to merge all unmerged changes from a source
12559  * branch into a target branch.
12560  *
12561  * Set @a *merge_p to the information needed to merge all unmerged changes
12562  * (up to @a source_revision) from the source branch @a source_path_or_url
12563  * at @a source_revision into the target WC at @a target_abspath.
12564  *
12565  * The flags @a allow_mixed_rev, @a allow_local_mods and
12566  * @a allow_switched_subtrees enable merging into a WC that is in any or all
12567  * of the states described by their names, but only if this function decides
12568  * that the merge will be in the same direction as the last automatic merge.
12569  * If, on the other hand, the last automatic merge was in the opposite
12570  * direction, then such states of the WC are not allowed regardless
12571  * of these flags.  This function merely records these flags in the
12572  * @a *merge_p structure; do_automatic_merge_locked() checks the WC
12573  * state for compliance.
12574  *
12575  * Allocate the @a *merge_p structure in @a result_pool.
12576  */
12577 static svn_error_t *
12578 client_find_automatic_merge(automatic_merge_t **merge_p,
12579                             const char *source_path_or_url,
12580                             const svn_opt_revision_t *source_revision,
12581                             const char *target_abspath,
12582                             svn_boolean_t allow_mixed_rev,
12583                             svn_boolean_t allow_local_mods,
12584                             svn_boolean_t allow_switched_subtrees,
12585                             svn_client_ctx_t *ctx,
12586                             apr_pool_t *result_pool,
12587                             apr_pool_t *scratch_pool)
12588 {
12589   source_and_target_t *s_t = apr_palloc(result_pool, sizeof(*s_t));
12590   automatic_merge_t *merge = apr_palloc(result_pool, sizeof(*merge));
12591
12592   SVN_ERR_ASSERT(svn_dirent_is_absolute(target_abspath));
12593
12594   /* "Open" the target WC.  Check the target WC for mixed-rev, local mods and
12595    * switched subtrees yet to faster exit and notify user before contacting
12596    * with server.  After we find out what kind of merge is required, then if a
12597    * reintegrate-like merge is required we'll do the stricter checks, in
12598    * do_automatic_merge_locked(). */
12599   SVN_ERR(open_target_wc(&s_t->target, target_abspath,
12600                          allow_mixed_rev,
12601                          allow_local_mods,
12602                          allow_switched_subtrees,
12603                          ctx, result_pool, scratch_pool));
12604
12605   if (!s_t->target->loc.url)
12606     return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
12607                              _("Can't perform automatic merge into '%s' "
12608                                "because it is locally added and therefore "
12609                                "not related to the merge source"),
12610                              svn_dirent_local_style(target_abspath,
12611                                                     scratch_pool));
12612
12613   /* Open RA sessions to the source and target trees. */
12614   SVN_ERR(svn_client_open_ra_session2(&s_t->target_ra_session,
12615                                       s_t->target->loc.url,
12616                                       s_t->target->abspath,
12617                                       ctx, result_pool, scratch_pool));
12618   SVN_ERR(svn_client__ra_session_from_path2(
12619             &s_t->source_ra_session, &s_t->source,
12620             source_path_or_url, NULL, source_revision, source_revision,
12621             ctx, result_pool));
12622
12623   /* Check source is in same repos as target. */
12624   SVN_ERR(check_same_repos(s_t->source, source_path_or_url,
12625                            &s_t->target->loc, target_abspath,
12626                            TRUE /* strict_urls */, scratch_pool));
12627
12628   SVN_ERR(find_automatic_merge(&merge->base, &merge->is_reintegrate_like, s_t,
12629                                ctx, result_pool, scratch_pool));
12630   merge->yca = s_t->yca;
12631   merge->right = s_t->source;
12632   merge->target = &s_t->target->loc;
12633   merge->allow_mixed_rev = allow_mixed_rev;
12634   merge->allow_local_mods = allow_local_mods;
12635   merge->allow_switched_subtrees = allow_switched_subtrees;
12636
12637   *merge_p = merge;
12638
12639   /* TODO: Close the source and target sessions here? */
12640
12641   return SVN_NO_ERROR;
12642 }
12643
12644 /* Perform an automatic merge, given the information in MERGE which
12645  * must have come from calling client_find_automatic_merge().
12646  *
12647  * Four locations are inputs: YCA, BASE, RIGHT, TARGET, as shown
12648  * depending on whether the base is on the source branch or the target
12649  * branch of this merge.
12650  *
12651  *                            RIGHT     (is_reintegrate_like)
12652  *          o-----------o-------o---
12653  *         /    prev.  /         \
12654  *   -----o     merge /           \  this
12655  *     YCA \         /             \ merge
12656  *          o-------o---------------o
12657  *                BASE            TARGET
12658  *
12659  * or
12660  *
12661  *                BASE        RIGHT      (! is_reintegrate_like)
12662  *          o-------o-----------o---
12663  *         /         \           \
12664  *   -----o     prev. \           \  this
12665  *     YCA \    merge  \           \ merge
12666  *          o-----------o-----------o
12667  *                                TARGET
12668  *
12669  * ### TODO: The reintegrate-like code path does not yet
12670  * eliminate already-cherry-picked revisions from the source.
12671  */
12672 static svn_error_t *
12673 do_automatic_merge_locked(conflict_report_t **conflict_report,
12674                           const automatic_merge_t *merge,
12675                           const char *target_abspath,
12676                           svn_depth_t depth,
12677                           svn_boolean_t diff_ignore_ancestry,
12678                           svn_boolean_t force_delete,
12679                           svn_boolean_t record_only,
12680                           svn_boolean_t dry_run,
12681                           const apr_array_header_t *merge_options,
12682                           svn_client_ctx_t *ctx,
12683                           apr_pool_t *result_pool,
12684                           apr_pool_t *scratch_pool)
12685 {
12686   merge_target_t *target;
12687   svn_boolean_t reintegrate_like = merge->is_reintegrate_like;
12688   svn_boolean_t use_sleep = FALSE;
12689   svn_error_t *err;
12690
12691   SVN_ERR(open_target_wc(&target, target_abspath,
12692                          merge->allow_mixed_rev && ! reintegrate_like,
12693                          merge->allow_local_mods && ! reintegrate_like,
12694                          merge->allow_switched_subtrees && ! reintegrate_like,
12695                          ctx, scratch_pool, scratch_pool));
12696
12697   if (reintegrate_like)
12698     {
12699       merge_source_t source;
12700       svn_ra_session_t *base_ra_session = NULL;
12701       svn_ra_session_t *right_ra_session = NULL;
12702       svn_ra_session_t *target_ra_session = NULL;
12703
12704       if (record_only)
12705         return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
12706                                 _("The required merge is reintegrate-like, "
12707                                   "and the record-only option "
12708                                   "cannot be used with this kind of merge"));
12709
12710       if (depth != svn_depth_unknown)
12711         return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
12712                                 _("The required merge is reintegrate-like, "
12713                                   "and the depth option "
12714                                   "cannot be used with this kind of merge"));
12715
12716       if (force_delete)
12717         return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
12718                                 _("The required merge is reintegrate-like, "
12719                                   "and the force_delete option "
12720                                   "cannot be used with this kind of merge"));
12721
12722       SVN_ERR(ensure_ra_session_url(&base_ra_session, merge->base->url,
12723                                     target->abspath, ctx, scratch_pool));
12724       SVN_ERR(ensure_ra_session_url(&right_ra_session, merge->right->url,
12725                                     target->abspath, ctx, scratch_pool));
12726       SVN_ERR(ensure_ra_session_url(&target_ra_session, target->loc.url,
12727                                     target->abspath, ctx, scratch_pool));
12728
12729       /* Check for and reject any abnormalities -- such as revisions that
12730        * have not yet been merged in the opposite direction -- that a
12731        * 'reintegrate' merge would have rejected. */
12732       {
12733         merge_source_t *source2;
12734
12735         SVN_ERR(find_reintegrate_merge(&source2, NULL,
12736                                        right_ra_session, merge->right,
12737                                        target_ra_session, target,
12738                                        ctx, scratch_pool, scratch_pool));
12739       }
12740
12741       source.loc1 = merge->base;
12742       source.loc2 = merge->right;
12743       source.ancestral = ! merge->is_reintegrate_like;
12744
12745       err = merge_cousins_and_supplement_mergeinfo(conflict_report,
12746                                                    &use_sleep,
12747                                                    target,
12748                                                    base_ra_session,
12749                                                    right_ra_session,
12750                                                    &source, merge->yca,
12751                                                    TRUE /* same_repos */,
12752                                                    depth,
12753                                                    FALSE /*diff_ignore_ancestry*/,
12754                                                    force_delete, record_only,
12755                                                    dry_run,
12756                                                    merge_options,
12757                                                    ctx,
12758                                                    result_pool, scratch_pool);
12759     }
12760   else /* ! merge->is_reintegrate_like */
12761     {
12762       /* Ignoring the base that we found, we pass the YCA instead and let
12763          do_merge() work out which subtrees need which revision ranges to
12764          be merged.  This enables do_merge() to fill in revision-range
12765          gaps that are older than the base that we calculated (which is
12766          for the root path of the merge).
12767
12768          An improvement would be to change find_automatic_merge() to
12769          find the base for each sutree, and then here use the oldest base
12770          among all subtrees. */
12771       apr_array_header_t *merge_sources;
12772       svn_ra_session_t *ra_session = NULL;
12773
12774       /* Normalize our merge sources, do_merge() requires this.  See the
12775          'MERGEINFO MERGE SOURCE NORMALIZATION' global comment. */
12776       SVN_ERR(ensure_ra_session_url(&ra_session, merge->right->url,
12777                                     target->abspath, ctx, scratch_pool));
12778       SVN_ERR(normalize_merge_sources_internal(
12779         &merge_sources, merge->right,
12780         svn_rangelist__initialize(merge->yca->rev, merge->right->rev, TRUE,
12781                                   scratch_pool),
12782         ra_session, ctx, scratch_pool, scratch_pool));
12783
12784       err = do_merge(NULL, NULL, conflict_report, &use_sleep,
12785                      merge_sources, target, ra_session,
12786                      TRUE /*related*/, TRUE /*same_repos*/,
12787                      FALSE /*ignore_mergeinfo*/, diff_ignore_ancestry,
12788                      force_delete, dry_run,
12789                      record_only, NULL, FALSE, FALSE, depth, merge_options,
12790                      ctx, result_pool, scratch_pool);
12791     }
12792
12793   if (use_sleep)
12794     svn_io_sleep_for_timestamps(target_abspath, scratch_pool);
12795
12796   SVN_ERR(err);
12797
12798   return SVN_NO_ERROR;
12799 }
12800
12801 svn_error_t *
12802 svn_client_get_merging_summary(svn_boolean_t *needs_reintegration,
12803                                const char **yca_url, svn_revnum_t *yca_rev,
12804                                const char **base_url, svn_revnum_t *base_rev,
12805                                const char **right_url, svn_revnum_t *right_rev,
12806                                const char **target_url, svn_revnum_t *target_rev,
12807                                const char **repos_root_url,
12808                                const char *source_path_or_url,
12809                                const svn_opt_revision_t *source_revision,
12810                                const char *target_path_or_url,
12811                                const svn_opt_revision_t *target_revision,
12812                                svn_client_ctx_t *ctx,
12813                                apr_pool_t *result_pool,
12814                                apr_pool_t *scratch_pool)
12815 {
12816   svn_boolean_t target_is_wc;
12817   automatic_merge_t *merge;
12818
12819   target_is_wc = (! svn_path_is_url(target_path_or_url))
12820                  && (target_revision->kind == svn_opt_revision_unspecified
12821                      || target_revision->kind == svn_opt_revision_working
12822                      || target_revision->kind == svn_opt_revision_base);
12823   if (target_is_wc)
12824     {
12825       const char *target_abspath;
12826
12827       SVN_ERR(svn_dirent_get_absolute(&target_abspath, target_path_or_url,
12828                                       scratch_pool));
12829       SVN_ERR(client_find_automatic_merge(
12830                 &merge,
12831                 source_path_or_url, source_revision,
12832                 target_abspath,
12833                 TRUE, TRUE, TRUE,  /* allow_* */
12834                 ctx, scratch_pool, scratch_pool));
12835     }
12836   else
12837     SVN_ERR(find_automatic_merge_no_wc(
12838               &merge,
12839               source_path_or_url, source_revision,
12840               target_path_or_url, target_revision,
12841               ctx, scratch_pool, scratch_pool));
12842
12843   if (needs_reintegration)
12844     *needs_reintegration = merge->is_reintegrate_like;
12845   if (yca_url)
12846     *yca_url = apr_pstrdup(result_pool, merge->yca->url);
12847   if (yca_rev)
12848     *yca_rev = merge->yca->rev;
12849   if (base_url)
12850     *base_url = apr_pstrdup(result_pool, merge->base->url);
12851   if (base_rev)
12852     *base_rev = merge->base->rev;
12853   if (right_url)
12854     *right_url = apr_pstrdup(result_pool, merge->right->url);
12855   if (right_rev)
12856     *right_rev = merge->right->rev;
12857   if (target_url)
12858     *target_url = apr_pstrdup(result_pool, merge->target->url);
12859   if (target_rev)
12860     *target_rev = merge->target->rev;
12861   if (repos_root_url)
12862     *repos_root_url = apr_pstrdup(result_pool, merge->yca->repos_root_url);
12863
12864   return SVN_NO_ERROR;
12865 }