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